Conversation
… runs Since goplus#3442, every trigger starts a new run of each registered callback and runs may overlap while one of them waits on the learner or on generation. That reproduces the stale-result race the review call discussed, and the agreed answer was cancelling or aborting stale processing rather than queueing. This lets the author say how runs of one callback, or of several callbacks, relate: CancelPrevious the joining run cancels the run holding the group; a cancelled run ends at its next waiting point and the result it was waiting on is discarded OneAtATime the joining run yields and waits for its turn SkipWhileBusy the joining run ends on the spot newRunGroup plus enter() lets a run join after filtering its trigger and lets callbacks of different events share one policy; a policy or a group given at registration joins from the first statement, through the __N overloads XGo groups. The author never checks a result: skipping and cancellation end the run through a sentinel that runFrame absorbs silently. yieldWhile is the only yield point and the only place cancellation takes effect, so a cancelled run never touches a pending result. Group state lives behind a leaf lock. The invariants checker pins the shape, the docs example and the debug seed course use a group, and the bundle build test exercises all three registration forms. The design is still under discussion in goplus#3509; this branch carries the implementation for that follow-up. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ethanlita
force-pushed
the
issue-3417-run-policies
branch
from
September 17, 2026 10:14
794b95d to
6eba292
Compare
This branch was successfully deployed
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.
Follow-up to #3442 for #3509. Draft until the design discussion in #3509 settles (concept and naming, how many forms, whether to ship for the first release).
Rebased onto the integration branch now that #3442 has merged, so the diff is this one commit. Its comments are written in English like the rest of the framework.
What this adds
Since #3442, every trigger starts a new run of each registered callback and runs may overlap while one of them waits on the learner or on generation. This PR lets the author say how runs of one callback, or of several callbacks, relate:
RunPolicy:CancelPrevious(the joining run cancels the run holding the group; a cancelled run ends at its next waiting point and the result it was waiting on is discarded),OneAtATime(the joining run yields and waits its turn),SkipWhileBusy(the joining run ends on the spot).newRunGroup(policy)andenter(); a group may be shared by callbacks of different events.onExit OneAtATime, code => {...}andonExit judging, code => {...}as sugar for joining from the first statement. Review preference so far is to ship a single form; these overloads are the part most likely to be dropped.runFrameabsorbs silently.Internally:
yieldWhileis the only yield point and the only place cancellation takes effect, so a cancelled run never touches a pending result; group state lives behind a leaf lock; the invariants checker pins the shape. Tests cover each policy, the shared group, result discarding, and registration-order starts; the bundle build test compiles all three registration forms through the real classfile pipeline.Not in scope
Actively cancelling a host call that is already pending (closing the dialog, aborting the generation) needs an executor-level cancellation protocol and host support; here a cancelled run only stops at its next waiting point.
🤖 Generated with Claude Code