-
Notifications
You must be signed in to change notification settings - Fork 1.7k
ENG-8258: API for linking and sharing states #6024
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
It works by defining a substate of SharedState and then calling self._link_to(target_token) from some event handler. from that point on, whenever that user's state is loaded, the StateManager will patch in the linked shared states. whenever a linked state is modified, we explicitly load all of the other linked tokens, patch in the modified states, and send a delta to those clients You can call ._unlink to remove the link association, which causes the substate to be subsequently loaded from the client_token's tree as a private state It is intended to work transparently with computed vars, background events, and frontend rendering.
CodSpeed Performance ReportMerging #6024 will improve performances by 3.38%Comparing Summary
Benchmarks breakdown
|
Greptile OverviewGreptile SummaryImplements an API for linking and sharing states across multiple clients by introducing Key Changes:
Main Issue Found:
Confidence Score: 4/5
Important Files ChangedFile Analysis
Sequence DiagramsequenceDiagram
participant C1 as Client1
participant C2 as Client2
participant A as App
participant SM as StateManager
participant SS as SharedState
Note over C1,SS: Initial Linking
C1->>A: link_to(shared_token)
A->>SM: modify_state_with_links
SM->>A: client1_state
A->>SS: perform link
SS->>SM: get shared_state (lock)
SS->>SS: add client1 to linked_from
SS->>SS: patch into tree
SS-->>C1: delta
Note over C1,SS: Second Client Links
C2->>A: link_to(shared_token)
A->>SM: modify_state_with_links
SM->>A: client2_state
A->>SS: perform link
SS->>SM: get shared_state (lock)
SS->>SS: add client2 to linked_from
SS->>SS: patch into tree
SS-->>C2: delta
Note over C1,SS: Modify Shared State
C1->>A: modify shared state
A->>SM: modify_state_with_links
A->>SS: apply changes
SS->>SS: track dirty vars
SS->>A: exit context
A->>SM: update_other_tokens(C2)
SM-->>C2: delta (async)
Note over C1,SS: Unlink
C1->>A: unlink
A->>SM: modify_state_with_links
A->>SS: perform unlink
SS->>SS: remove from links
SS->>SM: get private state
SS->>SS: patch private back
SS-->>C1: rehydrate
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
6 files reviewed, 2 comments
perform the subsequent updates in an asyncio.Task to allow the original caller to drop the lock for the other shared states.
the state might have multiple links, and we may have already entered the context and are holding the lock already, so we don't want to take the lock again which will hang. instead, check if the state is already linked to the target token and avoid doing extra work.
_modify_linked_states context can now release the locks of newly linked states and send updates for changes in newly linked states. rehydrating after linking is no longer necessary.
definitely the token will be different. although private-dependent data should use private states, it's common for llm generated code to define router_data dependent vars in the linked state itself, so we make that special case work
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
9 files reviewed, 1 comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements a new API for linking and sharing state between multiple clients in Reflex applications. It introduces the SharedState base class that allows different clients to share state by linking to a common token, enabling real-time state synchronization across sessions.
Key Changes:
- Introduces
rx.SharedStatemixin class with_link_to()and_unlink()methods for state sharing - Adds
_reflex_internal_linksbackend variable to track linked state mappings - Implements automatic state synchronization when linked states are modified
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
reflex/istate/shared.py |
New file implementing SharedState base classes and linking mechanisms |
reflex/istate/manager/__init__.py |
Adds modify_state_with_links() to handle linked state modifications |
reflex/app.py |
Updates state modification calls to use modify_state_with_links() |
reflex/state.py |
Adds _override_base_method decorator and _reflex_internal_links backend variable |
reflex/__init__.py |
Exports SharedState for public API |
tests/integration/test_linked_state.py |
Comprehensive integration tests for linked state functionality |
tests/units/test_state.py |
Updates test assertions to include new backend variable |
tests/integration/test_computed_vars.py |
Updates test assertions to include new backend variable |
pyi_hashes.json |
Updates type stub hash for API changes |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Hi @masenf this sounds like a great piece of a new functionality. Which use cases inspired you to implement this? Asked differently, when exactly should we consider using shared/linked states? |
It works by defining a substate of SharedState and then calling self._link_to(target_token) from some event handler. from that point on, whenever that user's state is loaded, the StateManager will patch in the linked shared states. whenever a linked state is modified, we explicitly load all of the other linked tokens, patch in the modified states, and send a delta to those clients
You can call ._unlink to remove the link association, which causes the substate to be subsequently loaded from the client_token's tree as a private state
It is intended to work transparently with computed vars, background events, and frontend rendering.
Test code
Access
/my-room-idto enter separate "rooms" for arbitrary sharing domains. This allows any number of clients to share state.