[HOS-333] Send a "reload" message to the frontend after state expiry
1. a state instance expires on the backing store 2. frontend attempts to process an event against the expired token and gets a fresh instance of the state without router_data set 3. backend sends a "reload" message on the websocket containing the event and immediately stops processing 4. in response to the "reload" message, frontend sends [hydrate, update client storage, on_load, <previous_event>] This allows the frontend and backend to re-syncronize on the state of the app before continuing to process regular events. If the event in (2) is a special hydrate event, then it is processed normally by the middleware and the "reload" logic is skipped since this indicates an initial load or a browser refresh.
This commit is contained in:
parent
d5a4182e24
commit
7624e3bb2f
@ -454,6 +454,10 @@ export const connect = async (
|
|||||||
queueEvents(update.events, socket);
|
queueEvents(update.events, socket);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
socket.current.on("reload", async (event) => {
|
||||||
|
event_processing = false;
|
||||||
|
queueEvents([...initialEvents(), JSON5.parse(event)], socket);
|
||||||
|
})
|
||||||
|
|
||||||
document.addEventListener("visibilitychange", checkVisibility);
|
document.addEventListener("visibilitychange", checkVisibility);
|
||||||
};
|
};
|
||||||
|
@ -73,6 +73,7 @@ from reflex.event import (
|
|||||||
EventSpec,
|
EventSpec,
|
||||||
EventType,
|
EventType,
|
||||||
IndividualEventType,
|
IndividualEventType,
|
||||||
|
get_hydrate_event,
|
||||||
window_alert,
|
window_alert,
|
||||||
)
|
)
|
||||||
from reflex.model import Model, get_db_status
|
from reflex.model import Model, get_db_status
|
||||||
@ -1259,6 +1260,21 @@ async def process(
|
|||||||
)
|
)
|
||||||
# Get the state for the session exclusively.
|
# Get the state for the session exclusively.
|
||||||
async with app.state_manager.modify_state(event.substate_token) as state:
|
async with app.state_manager.modify_state(event.substate_token) as state:
|
||||||
|
# When this is a brand new instance of the state, signal the
|
||||||
|
# frontend to reload before processing it.
|
||||||
|
if (
|
||||||
|
not state.router_data
|
||||||
|
and event.name != get_hydrate_event(state)
|
||||||
|
and app.event_namespace is not None
|
||||||
|
):
|
||||||
|
await asyncio.create_task(
|
||||||
|
app.event_namespace.emit(
|
||||||
|
"reload",
|
||||||
|
data=format.json_dumps(event),
|
||||||
|
to=sid,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
# re-assign only when the value is different
|
# re-assign only when the value is different
|
||||||
if state.router_data != router_data:
|
if state.router_data != router_data:
|
||||||
# assignment will recurse into substates and force recalculation of
|
# assignment will recurse into substates and force recalculation of
|
||||||
|
Loading…
Reference in New Issue
Block a user