-
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
base: main
Are you sure you want to change the base?
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 not alter performanceComparing Summary
|
Greptile OverviewGreptile SummaryThis PR implements Key Changes
Critical Issue Found
Confidence Score: 1/5
Important Files ChangedFile Analysis
Sequence DiagramsequenceDiagram
participant Client1
participant App
participant StateManager
participant SharedState1
participant LinkedToken
participant SharedState2
participant Client2
Note over Client1,Client2: Linking Process
Client1->>App: Event Handler calls _link_to(token)
App->>StateManager: modify_state_with_links(client1_token)
StateManager->>SharedState1: _modify_linked_states()
SharedState1->>StateManager: modify_state(linked_token)
StateManager->>LinkedToken: Lock and fetch state
LinkedToken-->>SharedState1: Return linked state
SharedState1->>SharedState1: Patch linked state into tree
SharedState1->>SharedState2: Update _linked_from set
SharedState1-->>Client1: Return hydrate events
Note over Client1,Client2: Propagation on Modification
Client1->>App: Modify shared state
App->>StateManager: modify_state_with_links(client1_token)
StateManager->>SharedState1: _modify_linked_states()
SharedState1->>StateManager: Lock linked_token states
SharedState1->>SharedState1: Apply changes to linked state
SharedState1->>SharedState1: Collect dirty_vars & affected_tokens
SharedState1->>App: Call app.modify_state for each affected_token
App->>StateManager: modify_state_with_links(client2_token, previous_dirty_vars)
StateManager->>SharedState2: _modify_linked_states(previous_dirty_vars)
SharedState2->>SharedState2: Apply dirty_vars to linked state
StateManager->>Client2: Send delta update
|
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
reflex/app.py
Outdated
| self, | ||
| token: str, | ||
| background: bool = False, | ||
| previous_dirty_vars: set[str] | None = None, |
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.
syntax: Type mismatch: previous_dirty_vars is declared as set[str] | None here, but _modify_linked_states expects dict[str, set[str]] | None (line 144 in reflex/istate/shared.py). This will cause a runtime error when propagating changes to linked states.
| previous_dirty_vars: set[str] | None = None, | |
| previous_dirty_vars: dict[str, set[str]] | None = None, |
Prompt To Fix With AI
This is a comment left during a code review.
Path: reflex/app.py
Line: 1568:1568
Comment:
**syntax:** Type mismatch: `previous_dirty_vars` is declared as `set[str] | None` here, but `_modify_linked_states` expects `dict[str, set[str]] | None` (line 144 in reflex/istate/shared.py). This will cause a runtime error when propagating changes to linked states.
```suggestion
previous_dirty_vars: dict[str, set[str]] | None = None,
```
How can I resolve this? If you propose a fix, please make it concise.
reflex/istate/manager/__init__.py
Outdated
| async def modify_state_with_links( | ||
| self, | ||
| token: str, | ||
| previous_dirty_vars: set[str] | None = None, |
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.
syntax: Type mismatch: previous_dirty_vars is declared as set[str] | None but should be dict[str, set[str]] | None to match _modify_linked_states expectations.
| previous_dirty_vars: set[str] | None = None, | |
| previous_dirty_vars: dict[str, set[str]] | None = None, |
Prompt To Fix With AI
This is a comment left during a code review.
Path: reflex/istate/manager/__init__.py
Line: 121:121
Comment:
**syntax:** Type mismatch: `previous_dirty_vars` is declared as `set[str] | None` but should be `dict[str, set[str]] | None` to match `_modify_linked_states` expectations.
```suggestion
previous_dirty_vars: dict[str, set[str]] | None = None,
```
How can I resolve this? If you propose a fix, please make it concise.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
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.