Repository navigation
fix(langgraph): persist cancellation record under durability='exit' - #8634
Closed
Ayush Baluni (aayushbaluni) wants to merge 1 commit into
Closed
Ayush Baluni (aayushbaluni) wants to merge 1 commit into
Ayush Baluni (aayushbaluni) wants to merge 1 commit into
Conversation
When a run is cancelled mid-superstep, the runner's commit() for the cancelled task appends an ERROR write and persists it. That commit runs from a done-callback which fires after AsyncPregelLoop.__aexit__ unwinds the stack. Under durability='async'/'sync' put_writes() forwards to the checkpointer immediately, so the record survives. Under durability='exit' writes are only flushed by _put_pending_writes() inside _suppress_interrupt, which has already run by then, so the ERROR write lands in checkpoint_pending_writes too late and is never persisted. The result was that get_state().tasks[...].error was None after a cancellation with durability='exit', while the other two modes reported CancelledError, so callers could not distinguish a task cancelled mid-flight from one that never started. Stage the cancellation for still-running tasks before the exit flush. Tasks that already produced writes are skipped, so completed work is untouched.
Contributor
|
This PR has been automatically closed because you are not assigned to the linked issue. External contributors must be assigned to an issue before opening a PR for it. Please:
Maintainers: reopen this PR or remove the |
3 of 4 tasks
6 tasks done
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.
Fixes #5672
Cancelling a run mid-superstep does not persist the cancellation when
durability="exit", soget_state().tasks[...].errorisNoneand callers cannot tell a task that was cancelled in flight from one that never started."async"and"sync"both record it correctly.The inconsistency
Two nodes in one superstep,
p1fast andp2slow; cancel whilep2is still running:Deterministic across repeated trials.
Root cause
PregelRunner.commit()appends(ERROR, exception)for a cancelled task (_runner.py:579-583), but it runs from a done-callback that fires afterAsyncPregelLoop.__aexit__unwinds the stack. Instrumenting the call order:With
"async"/"sync",put_writes()forwards to the checkpointer immediately (_loop.py:466), so the record survives. With"exit", writes are only flushed by_put_pending_writes()inside_suppress_interrupt(_loop.py:1334), which has already run, so the write lands incheckpoint_pending_writestoo late and is never persisted.Fix
Stage the cancellation for still-running tasks before the exit flush. Tasks that already produced writes are skipped, so a completed node's work is untouched and is never misreported as cancelled.
How I verified this
exitcase fail whileasync/syncstill pass, so the test measures the fix rather than decorating it.tests/test_pregel_async.py: 313 passed (310 on unmodifiedmain, +3 new).main). The 208 errors are byte-identical before and after and are postgres/redis fixtures I have no local service for.ruff checkandruff formatclean.Scope
Deliberately narrow. It does not attempt the terminal-receipt / lineage contract discussed in the issue thread, and does not touch the Platform-side question of whether Agent Server awaits the loop's cancellation cleanup before publishing
interrupted, which still looks Platform-owned.Note on process: the issue is still unassigned despite several contributors asking. Happy to close this if you would rather assign it to someone already waiting, or to re-scope it, since the defect fixed here is narrower than the originally reported symptom (which I could not reproduce on current
main; details in my comment).