fix(live): heartbeat the control channel so "live" reflects a reachable server #76
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/VAPP-66-control-heartbeat"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The statusbar's connection indicator ("live"/online) was driven solely by the
browser WebSocket
ready_state, which staysOPENwhen the server dies withouta clean TCP close (half-open connection, network partition, killed process). The
live driver opened the socket and waited, but never used the heartbeat the
protocol already supports, so the indicator could read "live" for an offline
server. This was a half-implemented feature.
vervain-server's control.ashx already answers an application-level
{"action":"ping"}with{"action":"pong"}(ControlIn::Ping->ControlOut::Pong); the browser driver just never spoke it. Add a pure,tick-driven
Heartbeatstate machine that sends apingroughly every 30 s and,if no frame answers within a ~10 s pong window, reports the socket dead. The wasm
driver records every inbound frame as activity, advances the heartbeat each poll
tick, and on
Deadtears the socket down so the reconnect loop activelyre-verifies reachability. "live" is reasserted only after a fresh socket reopens,
which is itself a reachability check. Any inbound frame (the pong or any server
push) counts as proof of life, so a busy connection is never torn down.
The heartbeat logic is a pure state machine gated
wasm OR test(like the framedecoder) and unit-tested on the server build; a compile-time assertion enforces
that the pong timeout stays below the ping interval so the staleness window
always closes.
#VAPP-66
The statusbar's connection indicator ("live"/online) was driven solely by the browser WebSocket `ready_state`, which stays `OPEN` when the server dies without a clean TCP close (half-open connection, network partition, killed process). The live driver opened the socket and waited, but never used the heartbeat the protocol already supports, so the indicator could read "live" for an offline server. This was a half-implemented feature. vervain-server's control.ashx already answers an application-level `{"action":"ping"}` with `{"action":"pong"}` (`ControlIn::Ping` -> `ControlOut::Pong`); the browser driver just never spoke it. Add a pure, tick-driven `Heartbeat` state machine that sends a `ping` roughly every 30 s and, if no frame answers within a ~10 s pong window, reports the socket dead. The wasm driver records every inbound frame as activity, advances the heartbeat each poll tick, and on `Dead` tears the socket down so the reconnect loop actively re-verifies reachability. "live" is reasserted only after a fresh socket reopens, which is itself a reachability check. Any inbound frame (the pong or any server push) counts as proof of life, so a busy connection is never torn down. The heartbeat logic is a pure state machine gated `wasm OR test` (like the frame decoder) and unit-tested on the server build; a compile-time assertion enforces that the pong timeout stays below the ping interval so the staleness window always closes. #VAPP-66