Skip to content

support async context for mutable proxies#6691

Open
harsh21234i wants to merge 5 commits into
reflex-dev:mainfrom
harsh21234i:fix/mutable-proxy-async-context-6689
Open

support async context for mutable proxies#6691
harsh21234i wants to merge 5 commits into
reflex-dev:mainfrom
harsh21234i:fix/mutable-proxy-async-context-6689

Conversation

@harsh21234i

Copy link
Copy Markdown

Fixes #6689

Summary

  • add async context-manager support to MutableProxy and
    ImmutableMutableProxy
  • refresh the proxy from its bound state field after entering the state
    context
  • cover ImmutableMutableProxy mutation through async with proxy

Testing

  • uv run pytest tests/units/
    test_state.py::test_immutable_mutable_proxy_async_context_manager tests/
    units/test_state.py::test_rebind_mutable_proxy tests/units/istate/
    test_proxy.py -q
  • uv run ruff check reflex/istate/proxy.py tests/units/test_state.py
  • uv run towncrier check --config pyproject.toml --dir . --compare-with
    upstream/main

@harsh21234i harsh21234i requested a review from a team as a code owner June 30, 2026 08:04

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e0d0b19a90

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread reflex/istate/proxy.py
@greptile-apps

greptile-apps Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds async with proxy support to MutableProxy (and therefore ImmutableMutableProxy) so that background-task code can mutate nested state fields such as state.data["a"] without holding the top-level StateProxy for the entire task.

  • Path tracking: _wrap_recursive now threads an AccessSpec tuple through every __getattr__, __getitem__, and __iter__ call, recording the exact sequence of attribute/item accesses from the root field to the current proxy; this path is replayed in __aenter__ to re-bind __wrapped__ to the freshly-locked state's live value.
  • Async context protocol: __aenter__ acquires the owning StateProxy lock, replays the recorded path, and swaps in the refreshed wrapped value; __aexit__ releases the lock via the saved context_state; the aenter_ok guard and unconditional _self_actx_state = None reset in the except block ensure lock and state are cleaned up correctly on any failure, including asyncio.CancelledError.
  • Iter-path rejection: proxies obtained via __iter__ record ("iter", None) which deliberately cannot be replayed (no stable key), causing a clear RuntimeError; the three new test cases cover the happy path, iter rejection, and failed-enter recovery.

Confidence Score: 5/5

Safe to merge; the new async context manager path correctly acquires and releases the state lock in all exit scenarios and the three new test cases exercise all documented failure modes.

The aenter_ok flag plus the unconditional _self_actx_state = None reset in the except block address the edge case raised in the previous review thread. Path tracking is consistent across all three access patterns, with the iter case deliberately rejected. No silent failure modes remain.

No files require special attention.

Important Files Changed

Filename Overview
reflex/istate/proxy.py Adds aenter/aexit to MutableProxy with access-path tracking to allow ImmutableMutableProxy to refresh from its state field; path replay supports attr/item access but correctly rejects iter-sourced proxies; exception safety is properly handled with the aenter_ok flag and unconditional _self_actx_state reset in the except block.
tests/units/test_state.py Adds three new async test cases covering happy-path mutation, iter-proxy rejection, and failed-enter recovery; coverage is thorough and validates all documented failure modes.
news/6689.feature.md Changelog entry for the new async context manager feature.

Reviews (5): Last reviewed commit: "Handle mutable proxy enter failures" | Re-trigger Greptile

Comment thread reflex/istate/proxy.py Outdated
Comment thread reflex/istate/proxy.py Outdated
@codspeed-hq

codspeed-hq Bot commented Jun 30, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 15.26%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

❌ 2 regressed benchmarks
✅ 24 untouched benchmarks
⏩ 8 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
test_var_access[mutable_dataclass_list] 206.6 ms 251.5 ms -17.86%
test_var_access[mutable_dict] 88.5 ms 101.3 ms -12.57%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing harsh21234i:fix/mutable-proxy-async-context-6689 (7063e53) with main (86cf989)

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.

Comment thread reflex/istate/proxy.py
Comment thread reflex/istate/proxy.py Outdated
Comment thread reflex/istate/proxy.py Outdated
Comment thread reflex/istate/proxy.py
Comment thread reflex/istate/proxy.py Outdated
Comment thread reflex/istate/proxy.py Outdated
Comment thread reflex/istate/proxy.py Outdated
Comment thread reflex/istate/proxy.py Outdated
@harsh21234i

Copy link
Copy Markdown
Author

Addressed the review feedback in d8f12f3.

Changes made:

  • Added typed AccessSpec path entries for attr, item, and iter.
  • Updated _wrap_recursive to append a single new path segment internally.
  • Added _self_actx_state to internal proxy attrs.
  • Rejected nested async with proxy usage explicitly.
  • Made proxy __aexit__ idempotent when already exited.
  • Made async refresh path replay defensive and fail clearly for iteration-sourced proxies.
  • Added coverage for nested context rejection, idempotent exit, and iteration-derived proxy rejection.

Checks passed:

  • uv run pytest tests/units/test_state.py::test_immutable_mutable_proxy_async_context_manager tests/units/ test_state.py::test_immutable_mutable_proxy_async_context_rejects_iter_proxy tests/units/test_state.py::test_rebind_mutable_proxy tests/units/istate/ test_proxy.py -q
  • uv run ruff check reflex/istate/proxy.py tests/units/test_state.py
  • uv run ruff format --check reflex/istate/proxy.py tests/units/test_state.py
  • uv run pyright reflex/istate/proxy.py tests/units/test_state.py tests/units/istate/test_proxy.py

@harsh21234i harsh21234i requested a review from masenf July 2, 2026 04:02
Comment thread reflex/istate/proxy.py
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.

(Immutable)MutableProxy should support __aenter__ protocol

2 participants