Repository navigation
Kick: a close that tells the peer why and bounds the wait - #244
Conversation
|
9069d77 regenerates both lockfiles under 9.3.0. Bazel module overrides drop modules out of the lockfile, so I didn't use any. The one override was a repository override: the sandbox blocks the Generated by Claude Code |
|
The review panel ran against d8605c0 with four lenses (correctness, concurrency, tests/docs, altitude). 92ebe13 carries the fixes. Fixed:
Kept as is:
Mutation checks: 9 of 9 killed, including the two new guards. The new timing tests pass 15 times out of 15. Generated by Claude Code |
|
31ea055 fixes the move-assignment bug the panel found, which my last comment had left out of scope. It was pre-existing. The defaulted move-assignments of
Generated by Claude Code |
What
ADR-0022 amendment.
SessionRegistry::Close(id)was documented as the kick for a silent partition. On Beast it isn't one: its close is the graceful handshake, bounded only byrequest_timeout_seconds(30s). games_hub hit this when a phone that dropped off the network kept its player out of a chess game.WebSocket::Kick(CloseReason, grace): sends the close frame with an application code and reason, then tears the connection down after at mostgrace. On Beast,gracebecomes the handshake timeout for that one close. A kick that findsClose's handshake already running closes the socket under it.WebSocket::PeerCloseReason(): the close frame the peer ended the session with. A kicked client can then see e.g. 4001 "superseded" and stop redialing.EventStreamHandle::KickandSessionRegistry::Kick(id, why, grace)wrap it. Beast, the pair, the dialed client andJsonRpcStreamSocketimplement both members. The base defaults (KickisClose(), no peer reason) keep other implementors compiling. Bad codes or reasons fail fast (ADR-0009).Close/Kickno longer deadlocks when the transport completes the parked receive inline (the pair does). The stream was being destroyed inside the call, waiting on the pin that call held. Handles fromAsyncEventStreamnow keep the socket alive by ownership instead. Borrowed sockets are still pinned.The registry's
Closedoc no longer claims the silent-partition case.Not covered: any hub-side change. MoonBase bumps the pin and adopts
Kickin its own PR.Testing
Kick, plus theClosecontrol that pins why it exists; the code reaching a raw peer and the opal client; a normal close reading 1000; a kick mid-close.CloseandKick.bazel test //runtime/...: 38/38.--runs_per_test=15.websocket_acceptance_testandwebsocket_contract_consumer_testpass.-fno-exceptionsgate, the rest of the consumer module, codegen/goldens (untouched), and fuzz.Checklist
bazel test //...and(cd codegen && gradle build spotlessCheck)pass locally (runtime suite only; codegen untouched)Generated by Claude Code