RFC(events): lock ownership as a capability for delta flushes - #6921
Draft
adhami3310 wants to merge 2 commits into
Draft
RFC(events): lock ownership as a capability for delta flushes#6921adhami3310 wants to merge 2 commits into
adhami3310 wants to merge 2 commits into
Conversation
Merging this PR will not alter performance
Comparing Footnotes
|
Contributor
Greptile SummaryThis draft RFC introduces a
Confidence Score: 5/5The PR appears safe to merge because no blocking failure remains. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| reflex/istate/manager/init.py | Adds the guarded LockedRoot wrapper and the documented capability-minting function. |
| packages/reflex-base/src/reflex_base/event/processor/base_state_processor.py | Requires LockedRoot for delta flushing and mints it at audited lock-holding call sites. |
| tests/units/reflex_base/event/processor/test_base_state_processor.py | Updates lock-proof expectations and tests rejection of bare roots and direct wrapper construction. |
Reviews (5): Last reviewed commit: "chore: trigger CI against main base" | Re-trigger Greptile
This was referenced Aug 20, 2026
adhami3310
changed the base branch from
khaleel/background-unlocked-trailing-clean
to
main
August 20, 2026 21:31
adhami3310
changed the base branch from
main
to
khaleel/background-unlocked-trailing-clean
August 20, 2026 21:59
adhami3310
force-pushed
the
khaleel/rfc-locked-root
branch
from
August 21, 2026 18:04
7d8434b to
99f8127
Compare
Delta work on a shared state tree is only safe while the token lock is held, but nothing in the code records who holds it: chain_updates takes a bare BaseState, and whether the caller is inside modify_state is call site history. The lost-update bug fixed on this branch was exactly a caller flushing a root it no longer owned. Make ownership a value. mint_locked_root is the single audited claim of the precondition, LockedRoot is the proof, and chain_updates refuses a bare state with a TypeError. The proxy-yield gate keeps its logic but now mints at the one place the justification lives; every other minting site is inside the lock by construction. Enforcement is by convention plus one greppable constructor, as strong as Python allows. The other flush sites (app.modify_state, proxy exit, hydrate) can adopt the same shape as follow-up.
adhami3310
force-pushed
the
khaleel/rfc-locked-root
branch
from
August 21, 2026 18:29
99f8127 to
7b7e5ce
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.
RFC / draft for discussion — one of two competing shapes for hardening the delta-flush path after #6920. Not intended to merge as-is.
#6920 fixed a lost-update race where a background event flushed (snapshot, resolve, emit,
_clean()) a shared state tree after dropping the token lock. The fix gates the one bad caller. This RFC makes the class unrepresentable instead: delta flushes require proof of lock ownership.mint_locked_root(root)inreflex.istate.manageris the single, greppable, documented claim of "I hold the token lock for this root".LockedRootcannot be constructed any other way.chain_updatestakesLockedRoot | Noneand raisesTypeErroron a bareBaseState._rehydrate, the compatibility flush) mint inside theirmodify_stateblocks. The background-yield gate keeps its_is_mutable()logic but now mints at that one audited spot, which is where its justification already lived in a comment.Enforcement is convention plus one constructor guard — as strong as Python gets — but the payoff is that "who may flush" went from call-site history to a reviewable value, and any future unlocked flush is a loud
TypeErrorin development rather than a silent lost update in production.Not converted here (follow-up if the shape is liked):
app.modify_state,StateProxy.__aexit__, andState.hydratedo the same four-step flush inline and could take the same capability — ideally via one sharedDeltaFlushhelper replacing the four copies.Competing RFC: #6922 — instead of proving the lock, it makes the flush itself safe under concurrency (resolution-dirt ledger + selective clean), which additionally un-reverts the atomicity hardening that
test_linked_stateforced out of #6920. The two compose, but each is sufficient reviewed alone.Tests: the existing #6920 suite passes unchanged;
test_chain_updates_refuses_a_bare_root_statecovers the enforcement;tests/integration/test_linked_state.pypasses (the SharedState oracle).