Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions reflex/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2082,17 +2082,42 @@ async def on_connect(self, sid: str, environ: dict):
if isinstance(self._token_manager, RedisTokenManager):
# Make sure this instance is watching for updates from other instances.
self._token_manager.ensure_lost_and_found_task(self.emit_update)

query_params = urllib.parse.parse_qs(environ.get("QUERY_STRING", ""))
token_list = query_params.get("token", [])
if token_list:
await self.link_token_to_sid(sid, token_list[0])
else:
token = token_list[0] if token_list else None

if not token:
console.warn(f"No token provided in connection for session {sid}")
return

try:
# Detect reconnect (token seen before)
is_reconnect = token in self._token_manager.token_to_sid

# Always link first to ensure mappings are valid
await self.link_token_to_sid(sid, token)

# If this is a reconnect and backend has lost state, trigger reload
if is_reconnect:
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] Reconnect detected for expired state (token={token}), emitting reload"
)
await self.emit("reload", {"reason": "state_expired"}, to=sid)
return

except Exception as e:
console.warn(f"[Reflex] on_connect error for token {token}: {e}")

subprotocol = environ.get("HTTP_SEC_WEBSOCKET_PROTOCOL")
if subprotocol and subprotocol != constants.Reflex.VERSION:
console.warn(
f"Frontend version {subprotocol} for session {sid} does not match the backend version {constants.Reflex.VERSION}."
f"Frontend version {subprotocol} for session {sid} "
f"does not match backend version {constants.Reflex.VERSION}."
)

def on_disconnect(self, sid: str) -> asyncio.Task | None:
Expand Down