Fix state manager lock isolation - #6830
Conversation
Greptile SummaryThis PR fixes state-manager lock isolation by creating each manager’s internal lock per instance rather than once at class definition.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| reflex/istate/manager/memory.py | Creates the memory manager’s coordination lock per instance, matching the intended ownership boundary. |
| reflex/istate/manager/disk.py | Creates the disk manager’s coordination lock per instance without changing its constructor contract. |
| reflex/istate/manager/redis.py | Uses a per-instance lock factory while preserving the field’s existing init=False behavior. |
| tests/units/istate/manager/test_manager_locks.py | Adds focused regression coverage for lock isolation across all three manager implementations and isolates disk storage. |
| tests/units/test_state.py | Corrects the existing assertion to require distinct locks for distinct manager instances. |
Reviews (4): Last reviewed commit: "Isolate disk state manager lock test" | Re-trigger Greptile
Merging this PR will not alter performance
Comparing Footnotes
|
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
There was a problem hiding this comment.
1 issue found and verified against the latest diff
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="tests/units/istate/manager/test_manager_locks.py">
<violation number="1" location="tests/units/istate/manager/test_manager_locks.py:25">
P3: Instantiating `StateManagerDisk()` in this lock-isolation test runs `__post_init__`, which creates the real app states directory and `_purge_expired_states()` deletes any stale `.pkl` files in it — filesystem side effects that the lock-isolation assertion doesn't need. If the test is run against a real states dir, it can delete state files. Consider isolating this (e.g., point `REFLEX_STATE_MANAGER_DISK_DEBOUNCE_SECONDS`/states dir at a tmp_path, or construct the object via `object.__new__`/`dataclasses` without `__post_init__`).</violation>
</file>
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
Summary
Fixes #6829.
This changes backend state manager internals so each manager instance owns its own
_state_manager_lockinstead of sharing a lock created at class-definition time.Updated managers:
StateManagerMemoryStateManagerDiskStateManagerRedisRedis was included because it had the same
dataclasses.field(default=asyncio.Lock())pattern as memory and disk.Root cause
asyncio.Lock()was evaluated when the dataclass field was defined, so every instance of the same manager class received the same lock object.Using
default_factory=asyncio.Lockcreates a fresh lock per manager instance.The PR also corrects an existing unit-test assertion whose comment already said separate state-manager instances should not share locks, but whose assertion checked the opposite.
Validation
Result:
6 passed.Result:
6955 passed, 18 skipped.uv run towncrier check --config pyproject.toml --dir . --compare-with upstream/mainResult: found
news/6830.bugfix.md.Result: passed.