Commit Graph

12 Commits

Author SHA1 Message Date
Josh Creek 129b0c7ef0 fix(server): fan outbox events out to every control-plane replica
The Deployment runs two replicas, but WebSocket subscribers live only in
each process's in-memory hub. Every replica races to read the same
global unpublished outbox rows, and publishing succeeded even when the
winning replica held no matching local subscriber -- that replica then
set the single global published_at. A client connected to the other
replica never received the event, and delivery degraded further with
each replica added. REST recovery eventually converged, but short-lived
proposal transitions could be observed late or not at all.

Publish committed events through PostgreSQL LISTEN/NOTIFY so the replica
that owns the subscriber's connection delivers it, regardless of which
replica drained the row. The listener holds its own pgx connection --
LISTEN is session state, so a pooled database/sql connection cannot
carry it -- and reconnects with backoff, since losing it would silently
downgrade that replica's subscribers to REST-only recovery.

The fan-out is optional: without EventFanout configured, behaviour is
unchanged local-hub publication, which stays correct for a single
replica and for tests. Only outbox-sourced events are routed through it;
the in-request-path publishes remain local, as those are a latency
optimisation for the caller's own connection.

Fan-out needs a wire shape of its own because ControlPlaneEvent hides
PlayerID from clients, and the recipient is exactly what a peer replica
needs to route on.
2026-09-05 10:29:23 +01:00
Josh Creek e376e1e80d fix(multiplayer): align websocket assignment ids 2026-09-01 22:42:04 +01:00
Josh Creek 429fb87c08 fix(multiplayer): validate server event resource ids 2026-09-01 22:25:04 +01:00
Josh Creek 614b87f7e1 fix(multiplayer): bound websocket writes 2026-09-01 21:24:38 +01:00
Josh Creek 30a22c366b fix(multiplayer): harden websocket frame parser 2026-09-01 21:23:20 +01:00
Josh Creek 52e3d73678 fix(multiplayer): reject websocket caps before upgrade 2026-09-01 19:35:34 +01:00
Josh Creek da92be73ef feat(multiplayer): cap websocket connections per player 2026-09-01 19:27:45 +01:00
Josh Creek 515b06d97c feat(multiplayer): bound control-plane websocket traffic 2026-09-01 19:25:34 +01:00
Josh Creek 60fe2caf8f feat: publish matchmaking state events 2026-08-31 23:12:20 +01:00
Josh Creek 161d2cdceb fix: validate matchmaking event vocabulary 2026-08-31 23:10:31 +01:00
Josh Creek a4bc8cdac8 fix: close slow event subscribers safely 2026-08-31 23:09:16 +01:00
Josh Creek d258f17852 feat: add authenticated matchmaking event stream 2026-08-31 23:05:04 +01:00