5.0 KiB
5.0 KiB
Game-server enhanced infra: service-discovery + state-sync + timing
Package: @suaveplan/game-server
Status: PROPOSED
Type: feature
Why
Wave C-4 lands the three "enhanced" subsystems that ride on top of the wave-A/B core: a heart-beating game-instance registry for multi-host
discovery + load-balancing, a binary delta state-sync layer driven by @suaveplan/bitpacker (complementary to the JSON-delta state/state-sync
shipped in wave B-3), and a vector-clock causality tracker for distributed event ordering. Without these, the higher-level orchestrator cannot
fan a session across processes, ship compact state updates over WebRTC, or reason about who-saw-what when two clients race a move.
What changes
- ADDED:
GameInstanceRegistry— TTL-evicting in-memory registry of live instances with four load-balancing strategies (least-players,random,region-based,round-robin), region-latency map, capacity / health updates, filter+select discovery API, and 6 lifecycle event keys wired through the existingGameEventEmitter. - ADDED:
BitPackerStateSync<TState, TSchema>— bitpacker-backed binary state-sync with client-side prediction, server reconciliation, and frame interpolation. Uses@suaveplan/bitpacker'sBitPacker.pack/unpackfor the wire format. Coexists with the JSON-deltastate/state-syncfrom wave B-3. - ADDED:
VectorClockSync<TEventData>— distributed event-ordering layer built over@suaveplan/timing'screateVectorClock. Records game actions per session, detects concurrent actions, runslast-write-wins | merge | customconflict resolution, and supports request/response sync rounds against remote nodes. - ADDED: 5 error codes —
REGISTRY_INSTANCE_NOT_FOUND,REGISTRY_HEARTBEAT_EXPIRED,BITPACK_ENCODE_FAILED,BITPACK_DECODE_FAILED,VECTOR_CLOCK_NODE_UNKNOWN— appended toGAME_SERVER_CODES. - ADDED: 3 OTel instruments —
game_server.registry.instance_lifecycle_total(counter),game_server.state.bitpack_bytes(histogram),game_server.vector_clock.actions_total(counter). - ADDED: 3 package subpath exports:
./enhanced/service-discovery/game-instance-registry,./enhanced/state-sync/bitpacker-state-sync,./enhanced/timing/vector-clock-sync. - ADDED:
@suaveplan/bitpackerand@suaveplan/timingasworkspace:^runtime deps.
Out of scope
- Cross-process IPC for the registry (HTTP/gRPC façade) — the registry is the in-memory primitive; a transport façade is a separate package.
- Lamport-clock variant (only vector clocks ship; Lamport is the degenerate single-counter case).
- Bitpacker schema authoring helpers — callers supply their own
BitPackerSchema.
Source mapping
This change derives from ../suaveplan/packages/universal/game-server/src/enhanced/.
| Requirement | Source lines | Notes |
|---|---|---|
GameInstanceRegistry lifecycle (start/stop/register/deregister) |
service-discovery/game-instance-registry/game-instance-registry.ts L33-L94 |
Reworded; genesis injects Clock (no Date.now) and routes events through GameEventEmitter. |
| Heartbeat-TTL eviction | same file L340-L351 | Verbatim semantics; injectable Clock substituted for Date.now. |
| Load-balancing strategies | same file L258-L338 | All four strategies preserved; Rng injected for random. |
| Filter / select discovery | same file L138-L208 | Preserved. |
BitPackerStateSync pack/unpack/prediction/reconciliation/interpolation |
state-sync/bitpacker-state-sync/bitpacker-state-sync.ts L36-L307 |
Reworded; logger dep dropped (genesis OTel-only); enableDelta flag plumbed via BitPackerOptions. |
VectorClockSync.recordAction / receiveAction |
timing/vector-clock-sync/vector-clock-sync.ts L86-L147 |
Rewritten on top of genesis createVectorClock (no upstream VectorClockManager); causality compare uses vectorClockCompare. |
| Conflict resolution strategies | same file L320-L350 | Preserved (last-write-wins, merge, custom). |
| Causality chain + concurrent-group detection | same file L170-L205, L383-L414 | Preserved. |
Requirements with no source line
| Requirement | Justification |
|---|---|
Injectable Clock + IdGenerator everywhere a timestamp / id is minted |
Genesis enterprise rule — no implicit Date.now or Math.random. |
| OTel counters / histogram on every public path | Genesis observability baseline. |
Zod validation on GameInstanceRegistration and BitPackerStateSyncConfig input boundaries |
Genesis rule: typed boundary at every public entry. |
Five new error codes routed through GameServerError |
Upstream throws plain Error; genesis policy is typed errors with the stable code registry. |
Risks
- The genesis
timingpackage exposes onlycreateVectorClock(not the upstreamVectorClockManager). The rewrite preserves the upstream public surface ofVectorClockSyncbut is built on the simpler primitive — this is the documented divergence. - Coverage target is 100/100/100/100;
BitPackerStateSync.interpolatehas multi-branch lerp logic that requires careful test design.