feat(sidecar): protocol 2 — file by type, a cursor feed, and bounded history #2
Reference in New Issue
Block a user
No description provided.
Delete Branch "feat/phase-3-read-path"
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 sidecar now files a frame by its
typeand never by itskind. That is the dumb-forwarder property made structural:eventis appended to history,snapshotreplaces the board of its kind,replyis routed byreqId,controlis broadcast and kept nowhere. Ten new event kinds are no change here at all — which is the whole point when the thing that grows fastest is the catalogue.The rule is lifted out of the spawned event loop into a
Filingenum specifically so it can be asserted about rather than living in five arms of amatchno test can reach.A frame with no usable
typeis dropped and countedNever guessed at. Defaulting an absent one to
eventwould file a board as history — the presence board appended a few thousand times, which nothing reports and nobody notices until they wonder why the database is large.The count is on
/healthasuntyped_frames, because the failure it diagnoses — a plugin and a sidecar on different protocol versions, which the game link has no handshake to catch — otherwise presents to an operator as a website showing nothing while the game is plainly up.It caught exactly that within three seconds of first running, unplanned: a protocol 1 plugin still live on a retired rig dialled in, and its
server.hellowent straight into the counter.Boards, and an in-place migration
boardsgeneralises protocol 1's singleserver_staterow. A database made by protocol 1 is migrated in place: two indexed columns added by a guardedALTER, and the old board carried across. Without that carry-over an upgraded sidecar answers204until the game next connects, and the website reads that as never heard from — losing a server it has rendered for weeks, at the exact moment somebody upgraded the bridge. There is a test that builds a protocol 1 database by hand and opens it with this build.GET /feed— the ingest cursorOldest first, strictly after an id, with
lastIdandmore. A separate route rather than a flag on/events, because one route with two orderings serves the other one to every caller that forgets the parameter — and for the ingesting caller that means advancing its cursor past rows it never read.Omitting
sinceasks where the END is;since=0is the other question entirely. A module installed today against a month-old sidecar wants what happens next, and the two intentions must not be separated by whether somebody typed a parameter.Retention
[store].retain_days(default 14) prunes events hourly. Boards are never pruned — history grows and the present does not, and a pruned board is a server that has never connected.The CI this repo did not have
Phases 1 and 3 both wrote
cargo fmt,clippy -D warningsand a test suite, and both ran them by hand. A guard nothing invokes is a guard whose state nobody knows, and the repository that gets released had nothing gating it.44 tests pass; clippy clean at
-D warnings.Spec:
docs/rust-link/PROTOCOL.md§8 (RunicGateway/docs#255).🤖 Generated with Claude Code
https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4