Skip to content

feat(state): let delta coroutines drop their key via sentinel#6673

Open
FarhanAliRaza wants to merge 3 commits into
reflex-dev:mainfrom
FarhanAliRaza:re-auth-state
Open

feat(state): let delta coroutines drop their key via sentinel#6673
FarhanAliRaza wants to merge 3 commits into
reflex-dev:mainfrom
FarhanAliRaza:re-auth-state

Conversation

@FarhanAliRaza

Copy link
Copy Markdown
Contributor

A coroutine value in a delta can now resolve to _DROP_FROM_DELTA to omit its key, so inclusion that can only be decided asynchronously is deferred into the delta and resolved post-hoc by _resolve_delta. Emptied state subdicts are removed as well.

All Submissions:

  • Have you followed the guidelines stated in CONTRIBUTING.md file?
  • Have you checked to ensure there aren't any other open Pull Requests for the desired changed?

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)

New Feature Submission:

  • Does your submission pass the tests?
  • Have you linted your code locally prior to submission?

Changes To Core Features:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your core changes, as applicable?
  • Have you successfully ran tests with your changes locally?

A coroutine value in a delta can now resolve to _DROP_FROM_DELTA to omit
its key, so inclusion that can only be decided asynchronously is deferred
into the delta and resolved post-hoc by _resolve_delta. Emptied state
subdicts are removed as well.
@FarhanAliRaza FarhanAliRaza requested a review from a team as a code owner June 22, 2026 22:56
@codspeed-hq

codspeed-hq Bot commented Jun 22, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 26 untouched benchmarks
⏩ 8 skipped benchmarks1


Comparing FarhanAliRaza:re-auth-state (95e64eb) with main (590711e)

Open in CodSpeed

Footnotes

  1. 8 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@greptile-apps

greptile-apps Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces a _DROP_FROM_DELTA sentinel that delta-value coroutines can return to have their key omitted from the delta post-resolution, and rebinds EventContext to the target token inside modify_state so that fan-out tasks observe the correct session.

  • _resolve_delta now checks each awaited coroutine result against the sentinel by identity and removes the key (and any resulting empty state subdict) before the delta is sent to the client.
  • modify_state wraps the body in a contextlib.ExitStack that forks EventContext to the token under modification and restores the caller's context on exit, with a LookupError guard for call-sites that have no ambient event context.

Confidence Score: 5/5

Safe to merge; the sentinel drop logic is correct and the EventContext rebinding is properly scoped and restored.

Both changes are narrowly scoped: _resolve_delta only gains a sentinel identity-check with an empty-subdict cleanup, and modify_state's ExitStack pattern correctly restores context on both normal and exceptional exits.

reflex/state.py — Final should be added to the typing import block.

Important Files Changed

Filename Overview
reflex/state.py Adds _DROP_FROM_DELTA sentinel and updates _resolve_delta to drop sentinel-resolved keys and clean up empty subdicts. Logic is correct; Final is used in the annotation but not imported.
reflex/app.py modify_state now forks and rebinds EventContext to the token being modified using contextlib.ExitStack; restoration on exit is correct and the LookupError path is properly guarded.
tests/units/test_state.py Three new async tests cover coroutine resolution, sentinel-drop, and empty-subdict cleanup; all target the new _resolve_delta behaviour directly.
tests/units/test_app.py New async test verifies EventContext token rebinding within modify_state and restoration after exit.

Reviews (3): Last reviewed commit: "Update reflex/state.py" | Re-trigger Greptile

Comment thread reflex/state.py Outdated
Comment thread tests/units/test_state.py
Comment on lines +5007 to +5023
return value

delta = {"s1": {"gone": _coro(_DROP_FROM_DELTA), "stay": _coro("kept"), "plain": 3}}
resolved = await _resolve_delta(delta)
assert resolved == {"s1": {"stay": "kept", "plain": 3}}


async def test_resolve_delta_pops_subdict_emptied_by_drops():
"""A state subdict left empty after dropping all its keys is removed entirely."""
from reflex.state import _DROP_FROM_DELTA, _resolve_delta

async def _coro(value): # noqa: RUF029 - a trivial coroutine value for the delta
return value

delta = {"s1": {"only": _coro(_DROP_FROM_DELTA)}, "s2": {"keep": 1}}
resolved = await _resolve_delta(delta)
assert resolved == {"s2": {"keep": 1}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing multi-drop-in-same-subdict test

The existing subdict-emptying test (test_resolve_delta_pops_subdict_emptied_by_drops) only exercises the case where a single coroutine empties the subdict. The more interesting ordering-sensitive path — where two coroutines in the same subdict both resolve to _DROP_FROM_DELTA — isn't covered. The empty-check logic (if not delta[state_name]) relies on the second coroutine's raw coroutine object still being in the dict when the first drop's check runs; while the logic is correct, adding a test case like {"s1": {"a": _coro(_DROP_FROM_DELTA), "b": _coro(_DROP_FROM_DELTA)}} would pin this invariant explicitly.

FarhanAliRaza and others added 2 commits June 23, 2026 06:01
Out-of-band modify_state (e.g. the shared-state fan-out recomputing
another client's delta) runs in a task that copied the triggering
event's EventContext. Fork and rebind the context to the modified
token so consumers inside -- delta resolution, computed vars -- observe
that token rather than the actor's inherited one. No-op when no
EventContext is set.
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant