Separate CHASM scheduler execution phases - #40
Draft
chaptersix wants to merge 6 commits into
Draft
Conversation
chaptersix
force-pushed
the
sch-readable-execution-phases
branch
from
August 19, 2026 11:30
a76a062 to
3163bb4
Compare
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.
What changed?
InvokerExecuteTaskHandler.Executeinto three explicit phases: load state in a CHASM read transaction, execute external RPCs outside the transaction, and commit results in a CHASM update transaction.invoker_execute_task.go; process-buffer planning remains separate.MaxActionsPerExecutionbudget, and keeps retry lifecycle writes and successor scheduling in commit.Why?
Executeis a CHASM side-effect task, so CHASM invokes it without holding the component lock or an open component transaction. The handler must explicitly enterchasm.ReadComponentandchasm.UpdateComponentcallbacks when it needs safe access to the component tree. Those callbacks are the transactional boundaries: the read callback sees a consistent tree, while the update callback applies state changes and successor tasks together under CHASM's mutable-state conflict handling.The unlocked side-effect task is the right place for external RPCs, but it cannot retain pointers obtained from a component callback. Running the RPCs inside an update callback would instead extend lock ownership across unbounded network I/O. The load phase therefore enters a short read transaction, clones only the state needed by the RPCs, and exits before making any calls.
Because live scheduler state may change while the unlocked RPCs are in flight, the commit phase opens a new update transaction and compares each result with the exact state and position that produced it. A matching result is applied with the existing lifecycle transition helpers; a mismatched result is invalidated rather than written onto a different or already-updated entry. This preserves first-writer-wins behavior while StartWorkflow request IDs keep repeated external calls idempotent.
Stack: #35 -> #36 -> #38 -> #39 -> #40. This PR is based on #39.
How did you test it?
The functional suite was intentionally left to PR CI.
Potential risks
Commit now invalidates a loaded result whenever its exact expected state or position changed. The remaining live work is re-armed through the existing task helpers, and repeated StartWorkflow calls retain request-ID idempotency. No persisted schema, dynamic-config switch, or production fallback was added.