Carry per-node emit counts in the live snapshot
The brain graph counts node_executed events client-side and the websocket is torn down on every shell change, so anything a flow published during the navigation gap was lost. The bus now keeps a session tally per qualified node and the snapshot hands it back, letting a reconnecting client catch up. Both the route and the tunnel connector build that snapshot from one helper so the portal cannot drift from the direct connection. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HTsT1isxUjw5gtkJk8WhuA
This commit is contained in:
@@ -730,6 +730,25 @@ def read_message_history(
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def snapshot_payload(controller: FlowController) -> dict[str, Any]:
|
||||
"""Everything a client needs to catch up, sent the moment it connects.
|
||||
|
||||
Also sent by the tunnel connector, which serves this websocket inline: the
|
||||
two have to agree, so they build the message here rather than each their
|
||||
own. ``emits`` is what the bus counted while nobody was listening — a
|
||||
client that reconnects between two pages would otherwise start from zero.
|
||||
"""
|
||||
return {
|
||||
"type": "snapshot",
|
||||
"values": controller.values(),
|
||||
"nodes": [s.model_dump() for s in controller.node_statuses()],
|
||||
"issues": [i.model_dump() for i in controller.issues],
|
||||
"paused": controller.paused_flows(),
|
||||
"logs": list(event_bus.recent_logs),
|
||||
"emits": dict(event_bus.emits),
|
||||
}
|
||||
|
||||
|
||||
@ws_router.websocket("/ws")
|
||||
async def flow_events(websocket: WebSocket, token: str = "") -> None:
|
||||
"""Stream values, node status and execution events as they happen.
|
||||
@@ -749,16 +768,7 @@ async def flow_events(websocket: WebSocket, token: str = "") -> None:
|
||||
websocket.app.state, "flow_controller", None
|
||||
)
|
||||
if controller is not None:
|
||||
await websocket.send_json(
|
||||
{
|
||||
"type": "snapshot",
|
||||
"values": controller.values(),
|
||||
"nodes": [s.model_dump() for s in controller.node_statuses()],
|
||||
"issues": [i.model_dump() for i in controller.issues],
|
||||
"paused": controller.paused_flows(),
|
||||
"logs": list(event_bus.recent_logs),
|
||||
}
|
||||
)
|
||||
await websocket.send_json(snapshot_payload(controller))
|
||||
|
||||
async with event_bus.subscribe() as queue:
|
||||
receiver = asyncio.create_task(websocket.receive_text())
|
||||
|
||||
Reference in New Issue
Block a user