From 1b46c3de18b16bf7ba64579e7f996a80a95b9a38 Mon Sep 17 00:00:00 2001 From: Laimonas Turauskas Date: Fri, 30 Jun 2023 16:45:27 -0700 Subject: [PATCH] Re-organize FormulaRuntime. --- .../com/instacart/formula/FormulaRuntime.kt | 103 ++++++++---------- 1 file changed, 46 insertions(+), 57 deletions(-) diff --git a/formula/src/main/java/com/instacart/formula/FormulaRuntime.kt b/formula/src/main/java/com/instacart/formula/FormulaRuntime.kt index 294368fa..95f97430 100644 --- a/formula/src/main/java/com/instacart/formula/FormulaRuntime.kt +++ b/formula/src/main/java/com/instacart/formula/FormulaRuntime.kt @@ -47,9 +47,7 @@ class FormulaRuntime( forceRun() hasInitialFinished = true - lastOutput?.let { - onOutput(it) - } + emitOutputIfNeeded(isInitialRun = true) } else { forceRun() } @@ -71,59 +69,60 @@ class FormulaRuntime( effectQueue.addLast(it) } - run(shouldEvaluate = evaluate) + run(evaluate = evaluate) } override fun onPostponedTransition(event: Event) { event.dispatch() } - private fun forceRun() = run(shouldEvaluate = true) + private fun forceRun() = run(evaluate = true) /** * Performs the evaluation and execution phases. * - * @param shouldEvaluate Determines if evaluation needs to be run. + * @param evaluate Determines if evaluation needs to be run. */ - private fun run(shouldEvaluate: Boolean) { + private fun run(evaluate: Boolean) { if (isEvaluating) return try { - val freshRun = !isExecuting - if (freshRun) { - inspector?.onRunStarted(shouldEvaluate) - } + runFormula(evaluate) + emitOutputIfNeeded(isInitialRun = false) + } catch (e: Throwable) { + isEvaluating = false + + manager?.markAsTerminated() + onError(e) + manager?.performTerminationSideEffects() + } + } - val manager = checkNotNull(manager) - val currentInput = checkNotNull(input) + private fun runFormula(evaluate: Boolean) { + val freshRun = !isExecuting + if (freshRun) { + inspector?.onRunStarted(evaluate) + } + + val manager = checkNotNull(manager) + val currentInput = checkNotNull(input) + if (evaluate && !manager.terminated) { isEvaluating = true - if (shouldEvaluate && !manager.terminated) { - evaluationPhase(manager, currentInput) - } + evaluationPhase(manager, currentInput) isEvaluating = false + } - if (shouldEvaluate || effectQueue.isNotEmpty()) { - executionRequested = true - } - if (isExecuting) return + if (evaluate || effectQueue.isNotEmpty()) { + executionRequested = true + } - effectPhase(manager) + if (isExecuting) return - if (freshRun) { - inspector?.onRunFinished() - } + executeEffects() - if (hasInitialFinished && emitOutput) { - emitOutput = false - onOutput(checkNotNull(lastOutput)) - } - } catch (e: Throwable) { - isEvaluating = false - - manager?.markAsTerminated() - onError(e) - manager?.performTerminationSideEffects() + if (freshRun) { + inspector?.onRunFinished() } } @@ -149,38 +148,28 @@ class FormulaRuntime( } } - /** - * Executes operations containing side-effects such as starting/terminating streams. - */ - private fun effectPhase(manager: FormulaManagerImpl) { - isExecuting = true - while (executionRequested) { - executionRequested = false - - val transitionId = manager.transitionID - // We execute pending side-effects even after termination - if (executeEffects(manager, transitionId)) { - continue - } - } - isExecuting = false - } - /** * Executes effects from the [effectQueue]. */ - private fun executeEffects(manager: FormulaManagerImpl<*, *, *>, transitionId: Long): Boolean { + private fun executeEffects() { + isExecuting = true + // Walk through the effect queue and execute them while (effectQueue.isNotEmpty()) { val effects = effectQueue.pollFirst() if (effects != null) { effects.execute() inspector?.onEffectExecuted() - - if (manager.hasTransitioned(transitionId)) { - return true - } } } - return false + isExecuting = false + } + + private fun emitOutputIfNeeded(isInitialRun: Boolean,) { + if (isInitialRun) { + lastOutput?.let(onOutput) + } else if (hasInitialFinished && emitOutput) { + emitOutput = false + onOutput(checkNotNull(lastOutput)) + } } }