Fix/Socket reconnection rehydrates#5966
Fix/Socket reconnection rehydrates#5966ParagGhatage wants to merge 3 commits intoreflex-dev:mainfrom
Conversation
…nects and reconnects by checking backend state still exists or is expired just after reconnect
Greptile OverviewGreptile SummaryAdds logic to detect expired backend state on socket reconnection and emit a reload event to the frontend. Key changes:
Critical issue found:
Confidence Score: 0/5
Important Files ChangedFile Analysis
Sequence DiagramsequenceDiagram
participant Frontend
participant Socket
participant on_connect
participant link_token_to_sid
participant StateManager
participant State
Frontend->>Socket: Reconnect with token
Socket->>on_connect: on_connect(sid, environ)
on_connect->>link_token_to_sid: link_token_to_sid(sid, token)
link_token_to_sid->>StateManager: modify_state(token)
StateManager->>State: get or create state
link_token_to_sid->>State: router_data[SESSION_ID] = sid
State-->>link_token_to_sid: state modified
link_token_to_sid-->>on_connect: completed
Note over on_connect,State: BUG: Check happens here AFTER router_data is populated
on_connect->>StateManager: get_state(token)
StateManager-->>on_connect: state (with router_data={SESSION_ID: sid})
on_connect->>State: check if not router_data
State-->>on_connect: False (router_data is NOT empty)
Note over on_connect: Reload never emitted!
on_connect-->>Socket: connection complete
|
| try: | ||
| if token: | ||
| substate_key = _substate_key(token, self.app.state_manager.state) | ||
| state = await self.app.state_manager.get_state(substate_key) | ||
| if not getattr(state, "router_data", None): | ||
| console.debug( | ||
| f"[Reflex] socket reconnect detected with expired token {token}, emitting reload" | ||
| ) | ||
| await self.emit("reload", data={"reason": "state expired"}, to=sid) |
There was a problem hiding this comment.
logic: logic bug: check for expired state occurs AFTER link_token_to_sid already populated router_data[SESSION_ID] (line 2089 calls this, which sets router_data at line 2287). By the time this check runs, router_data is {SESSION_ID: sid}, so not getattr(state, "router_data", None) is always False. The reload will never be emitted.
move this check BEFORE line 2089, or check if router_data was empty before link_token_to_sid modified it
Prompt To Fix With AI
This is a comment left during a code review.
Path: reflex/app.py
Line: 2093:2101
Comment:
**logic:** logic bug: check for expired state occurs AFTER `link_token_to_sid` already populated `router_data[SESSION_ID]` (line 2089 calls this, which sets `router_data` at line 2287). By the time this check runs, `router_data` is `{SESSION_ID: sid}`, so `not getattr(state, "router_data", None)` is always `False`. The reload will never be emitted.
move this check BEFORE line 2089, or check if `router_data` was empty before `link_token_to_sid` modified it
How can I resolve this? If you propose a fix, please make it concise.|
@masenf , |
masenf
left a comment
There was a problem hiding this comment.
this doesn't work for me at all. it tries to send "reload" on the initial connection with an invalid payload.
did you test this? did it work for you?
CodSpeed Performance ReportMerging #5966 will not alter performanceComparing Summary
|
@masenf, Also saw your PR #5969 - makes total sense to move this logic to the frontend and handle rehydration directly through the backend instead of a full reload. |
All Submissions:
Type of change
Please delete options that are not relevant.
Changes To Core Features:
After these steps, you're ready to open a pull request.
Fix: Reload frontend on socket reconnect when backend state has expired
Description
This PR fixes the issue where the frontend retains stale state when the backend state has expired, and the socket reconnects silently.
Problem
Previously, the backend only emitted a
reloadevent when an incoming frontend event (e.g., a click) triggered state access.When the socket reconnected automatically - without any user interaction - the stale frontend state remained until the next user action caused rehydration.
Fix
on_connect()inapp.pyto check the backend state immediately after reconnect.router_data, a"reload"event is emitted instantly to the client.Behavior Summary
✅ Detects expired backend state right after reconnect.
✅ Emits
"reload"to prompt frontend rehydration.✅ Prevents users from seeing stale UI after backend restarts or token expiry.
Linked Issue
Closes #5963