Fix df.loop continue_as_new restarting from graph root when loop is not root#228
Open
Copilot wants to merge 2 commits into
Open
Fix df.loop continue_as_new restarting from graph root when loop is not root#228Copilot wants to merge 2 commits into
Copilot wants to merge 2 commits into
Conversation
…ot root Co-authored-by: pinodeca <32303022+pinodeca@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix df.loop continue_as_new restart behavior
Fix df.loop continue_as_new restarting from graph root when loop is not root
Jun 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
df.loopcalledcontinue_as_newinline in the main orchestration, so every new generation restarted fromgraph.root_node_id— re-executing prefix nodes on every loop iteration. Forprefix ~> df.loop(body), the prefix ran once per iteration instead of once per instance.A sub-orchestration approach was evaluated but is blocked by a duroxide 0.1.29 limitation:
ContinueAsNewdrops the parent link, so the parent orchestration never receives the child's completion.Approach: loop-continue sentinel
Instead of calling
continue_as_newinsideexecute_loop_node, the loop returns an upward-propagating sentinel that the rootexecute()handles:On the next generation,
execute()resumes fromrestart_node_idwith pre-populatedresults, skipping any prefix nodes.Changes
src/orchestrations/execute_function_graph.rsexecute_loop_node: returns__loop_continue__sentinel instead of callingcontinue_as_newexecute_then_node: propagates sentinel from RIGHT child unchanged; when sentinel comes from LEFT child, promotesrestart_node_idto the THEN node itself so the right-side suffix is included in the restart pathexecute(): detects sentinel, callscontinue_as_newwithLoopContinuationpointing at the loop node (or nearest enclosing THEN forloop ~> suffix)BTreeMapfor deterministic JSON key order — required for duroxide replay correctnessexecute_loop/LOOP_NAMEsub-orchestrationsrc/types.rs: addsLoopContinuationstruct andloop_continuation: Option<LoopContinuation>toFunctionInput(backward-compatible; absent on initial invocation)tests/e2e/sql/24_nonroot_loop.sql: regression tests for three non-root loop shapes:prefix ~> loop— prefix runs once, body runs N timesprefix ~> loop ~> suffix— prefix and suffix each run once