Skip to content

Commit 75d31c7

Browse files
Fix Conflate Stale to Work with Short Circuit
1 parent dc32e4c commit 75d31c7

File tree

1 file changed

+30
-17
lines changed

1 file changed

+30
-17
lines changed

workflow-runtime/src/commonMain/kotlin/com/squareup/workflow1/RenderWorkflow.kt

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -161,16 +161,16 @@ public fun <PropsT, OutputT, RenderingT> renderWorkflowIn(
161161
}
162162

163163
/**
164-
* If [runtimeConfig] contains [RuntimeConfigOptions.RENDER_ONLY_WHEN_STATE_CHANGES] then
165-
* send any output, but return true which means restart the runtime loop and process another
166-
* action.
164+
* If [runtimeConfig] contains [RuntimeConfigOptions.RENDER_ONLY_WHEN_STATE_CHANGES] and
165+
* we have not changed state, then return true to short circuit.
167166
*/
168-
suspend fun shortCircuitForUnchangedState(actionResult: ActionProcessingResult): Boolean {
167+
fun shortCircuitForUnchangedState(
168+
actionResult: ActionProcessingResult
169+
): Boolean {
169170
if (runtimeConfig.contains(RENDER_ONLY_WHEN_STATE_CHANGES) &&
170171
actionResult is ActionApplied<*> && !actionResult.stateChanged
171172
) {
172173
// Possibly send output and process more actions. No state change so no re-render.
173-
sendOutput(actionResult, onOutput)
174174
return true
175175
}
176176
return false
@@ -183,35 +183,48 @@ public fun <PropsT, OutputT, RenderingT> renderWorkflowIn(
183183
// launched.
184184
var actionResult: ActionProcessingResult = runner.processAction()
185185

186-
if (shortCircuitForUnchangedState(actionResult)) continue
186+
if (shortCircuitForUnchangedState(actionResult)) {
187+
sendOutput(actionResult, onOutput)
188+
continue
189+
}
190+
191+
// Most often a list of one, but with CONFLATE_STALE_RENDERINGS, we may build up others.
192+
val listOfOutputs = mutableListOf(actionResult)
187193

188194
// After resuming from runner.processAction() our coroutine could now be cancelled, check so
189195
// we don't surprise anyone with an unexpected rendering pass. Show's over, go home.
190196
if (!isActive) return@launch
191197

198+
// Next Render Pass.
192199
var nextRenderAndSnapshot: RenderingAndSnapshot<RenderingT> = runner.nextRendering()
193200

194201
if (runtimeConfig.contains(CONFLATE_STALE_RENDERINGS)) {
195-
// Only null will allow us to continue processing actions and conflating stale renderings.
196-
// If this is not null, then we had an Output and we want to send it with the Rendering
197-
// (stale or not).
198-
while (actionResult is ActionApplied<*> && actionResult.output == null) {
199-
// We have more actions we can process, so this rendering is stale.
202+
while (isActive && actionResult is ActionApplied<*>) {
203+
// We may have more actions we can process, this rendering could be stale.
200204
actionResult = runner.processAction(waitForAnAction = false)
201205

202-
if (!isActive) return@launch
203-
204-
// If no actions processed, then no new rendering needed.
206+
// If no actions processed, then no new rendering needed. Pass on to UI.
205207
if (actionResult == ActionsExhausted) break
206208

209+
if (shortCircuitForUnchangedState(actionResult)) {
210+
listOfOutputs.add(actionResult)
211+
continue
212+
}
213+
214+
// Make sure the runtime has not been cancelled.
215+
if (!isActive) return@launch
216+
207217
nextRenderAndSnapshot = runner.nextRendering()
208218
}
209219
}
210220

211-
// Pass on to the UI.
221+
// Pass on the rendering to the UI.
212222
renderingsAndSnapshots.value = nextRenderAndSnapshot
213-
// And emit the Output.
214-
sendOutput(actionResult, onOutput)
223+
224+
// Emit the Output(s).
225+
listOfOutputs.forEach { actionApplied ->
226+
sendOutput(actionApplied, onOutput)
227+
}
215228
}
216229
}
217230

0 commit comments

Comments
 (0)