Repository navigation
Compose runtime: refresh workflow implementation when its instance changes [CLF-654] - #1591
Conversation
|
🤖 Compose runtime microbenchmarks, I ran Allocations: unchanged in every benchmark. The ±1 differences are median noise. The fix adds an identity check per child render and allocates only when the instance actually changes, which none of these benchmarks do. Time: geometric mean of branch/main median time.
Deltas go both ways within each config. Full results (median time and allocation count)
|
When a parent renders a new instance of the same workflow type and key, the compose runtime keeps using the first instance for render, onPropsChanged, snapshotState and interceptors. The legacy runtime switches to the new instance and keeps the session's state. The render test is ported from #1577. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ew one ComposeRenderContext now swaps in the latest workflow instance, and re-intercepts it, whenever the parent passes a different instance of the same workflow. Session state stays as it was, which matches StatefulWorkflowNode.maybeUpdateCachedWorkflowInstance in the traditional runtime. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0b4d885 to
9172d05
Compare
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bafbfbf
into
zachklipp/clf-646-cache-render-context
Stacked on #1588, which should merge first. After rebasing, the cached
renderContextfrom #1588 stays as it is when the workflow instance changes:RenderContext(this, interceptedWorkflow)only uses the workflow argument for type inference and wraps nothing butthis. The benchmark comparison in the comments was measured againstmain, before this rebase.Fixes a finding from review of #1442 (comment).
ComposeRenderContextis remembered per workflow identity, but it kept the firstworkflowandinterceptedWorkflowit was created with. When a parent rendered a new instance of the same workflow type and key, the compose runtime still calledrender,onPropsChangedandsnapshotStateon the old instance, so it could hold on to stale constructor dependencies. The legacy runtime (StatefulWorkflowNode.maybeUpdateCachedWorkflowInstance()) switches to the new instance, re-intercepts it, and keeps the session's state.Tests (first commit)
Added to
RenderWorkflowInTest. In each one, the parent renders a new child instance on every render pass:new_child_workflow_instance_is_used_to_render_without_resetting_state(ported from Add tests for Compose runtime review feedback [CLF-524] #1577):renderuses the new instance, and the child keeps its state.new_child_workflow_instance_is_used_for_onPropsChanged:onPropsChangedis called on the new instance.new_child_workflow_instance_is_used_for_snapshotState: a snapshot saved after the instance changed was written by the new instance.interceptor_renders_new_child_workflow_instance: an interceptor'sproceedrenders the new instance.Before the fix, all 4 failed on
COMPOSE_RUNTIME_NON_SKIPPINGandCOMPOSE_RUNTIME_SKIPPING(for exampleexpected:<v[1] props=1 state=1> but was:<v[0] props=1 state=1>), and passed on all 64 legacy runtime configs.Fix (second commit)
renderWorkflownow callsComposeRenderContext.updateWorkflow(workflow)on every pass. If the instance changed (identity check), it stores the new instance and re-intercepts it. Session state is left alone. The call happens before the skip check, so a child that skips this pass still uses the new instance for its next render and its snapshots.With the fix, all
:workflow-runtime:jvmTesttests pass.🤖 Generated with Claude Code