@chaos-overlords/server 0.8.1 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/app.js +10 -0
  2. package/dist/app.js.map +1 -1
  3. package/dist/container.d.ts +16 -0
  4. package/dist/container.d.ts.map +1 -1
  5. package/dist/container.js +5 -0
  6. package/dist/container.js.map +1 -1
  7. package/dist/http/contractJson.d.ts +32 -0
  8. package/dist/http/contractJson.d.ts.map +1 -0
  9. package/dist/http/contractJson.js +22 -0
  10. package/dist/http/contractJson.js.map +1 -0
  11. package/dist/http/errorHandler.d.ts.map +1 -1
  12. package/dist/http/errorHandler.js +45 -6
  13. package/dist/http/errorHandler.js.map +1 -1
  14. package/dist/http/middleware.d.ts +11 -0
  15. package/dist/http/middleware.d.ts.map +1 -1
  16. package/dist/http/middleware.js +71 -5
  17. package/dist/http/middleware.js.map +1 -1
  18. package/dist/http/responseValidation.d.ts.map +1 -1
  19. package/dist/http/responseValidation.js +5 -3
  20. package/dist/http/responseValidation.js.map +1 -1
  21. package/dist/http/types.d.ts +20 -0
  22. package/dist/http/types.d.ts.map +1 -1
  23. package/dist/index.d.ts +3 -2
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +3 -2
  26. package/dist/index.js.map +1 -1
  27. package/dist/routes/bugReports.d.ts.map +1 -1
  28. package/dist/routes/bugReports.js +13 -1
  29. package/dist/routes/bugReports.js.map +1 -1
  30. package/dist/routes/events.d.ts.map +1 -1
  31. package/dist/routes/events.js +26 -5
  32. package/dist/routes/events.js.map +1 -1
  33. package/dist/routes/lobby.d.ts.map +1 -1
  34. package/dist/routes/lobby.js +19 -7
  35. package/dist/routes/lobby.js.map +1 -1
  36. package/dist/routes/protocol.d.ts.map +1 -1
  37. package/dist/routes/protocol.js +2 -1
  38. package/dist/routes/protocol.js.map +1 -1
  39. package/dist/routes/snapshots.d.ts.map +1 -1
  40. package/dist/routes/snapshots.js +3 -2
  41. package/dist/routes/snapshots.js.map +1 -1
  42. package/dist/routes/turns.d.ts.map +1 -1
  43. package/dist/routes/turns.js +4 -3
  44. package/dist/routes/turns.js.map +1 -1
  45. package/dist/sse/LocalEventHub.d.ts +36 -10
  46. package/dist/sse/LocalEventHub.d.ts.map +1 -1
  47. package/dist/sse/LocalEventHub.js +75 -16
  48. package/dist/sse/LocalEventHub.js.map +1 -1
  49. package/dist/sse/MatchLog.d.ts +85 -0
  50. package/dist/sse/MatchLog.d.ts.map +1 -0
  51. package/dist/sse/MatchLog.js +147 -0
  52. package/dist/sse/MatchLog.js.map +1 -0
  53. package/dist/sse/createSseResponse.d.ts +27 -2
  54. package/dist/sse/createSseResponse.d.ts.map +1 -1
  55. package/dist/sse/createSseResponse.js +96 -14
  56. package/dist/sse/createSseResponse.js.map +1 -1
  57. package/package.json +7 -7
@@ -1,25 +1,46 @@
1
1
  import { INT32_MAX, listEventsContract, streamEventsContract } from '@chaos-overlords/contracts';
2
+ import { answering } from '../http/contractJson';
2
3
  import { requireMember } from '../http/guards';
3
4
  import { buildHonoRoute } from '../http/routes';
5
+ import { isReadableEvent } from '../sse/createSseResponse';
4
6
  /** The event log: a paged REST read (the fallback) and the SSE stream over the same log. */
5
7
  export function registerEventRoutes(api) {
6
8
  buildHonoRoute(api, listEventsContract, async (c) => {
7
9
  const principal = requireMember(c.get('principal'), c.req.valid('param').matchId);
8
10
  const { after, limit } = c.req.valid('query');
9
- const events = await c
10
- .get('container')
11
- .kernel.deps.storage.events.listAfter(principal.match.id, after, limit);
12
- return c.json({ events }, 200);
11
+ const container = c.get('container');
12
+ const events = await container.kernel.deps.storage.events.listAfter(principal.match.id, after, limit);
13
+ // A row this build's schema refuses is left out rather than answered as a 500. One reshaped
14
+ // payload — which a protocol-only upgrade may leave behind, and AGENTS.md says stored matches
15
+ // survive those — otherwise made every page holding it unreadable for the life of the match.
16
+ //
17
+ // The test is a validation, not a format: building the whole SSE frame here only to throw the
18
+ // string away meant serialising every event of the page an extra time, and `c.json` then
19
+ // serialised all of them again.
20
+ const readable = events.filter((event) => {
21
+ if (isReadableEvent(event))
22
+ return true;
23
+ container.kernel.deps.logger.warn('skipped an unreadable stored event', {
24
+ matchId: principal.match.id,
25
+ seq: event.seq,
26
+ });
27
+ return false;
28
+ });
29
+ return c.json(answering(c, { events: readable }), 200);
13
30
  });
14
31
  buildHonoRoute(api, streamEventsContract, async (c) => {
15
32
  const principal = requireMember(c.get('principal'), c.req.valid('param').matchId);
16
33
  const afterSeq = resumePoint(c.req.header('last-event-id'), c.req.query('after'));
17
- return c.get('container').eventStream.open({
34
+ const stream = await c.get('container').eventStream.open({
18
35
  matchId: principal.match.id,
19
36
  playerId: principal.player.id,
20
37
  afterSeq,
21
38
  signal: c.req.raw.signal,
22
39
  });
40
+ // The stream is a raw `Response`, and Hono does not merge the headers the middleware prepared
41
+ // into one of those — so the one response an operator most wants to correlate, a stream that
42
+ // misbehaved for an hour, was the only one without an `X-Request-Id`.
43
+ return c.newResponse(stream.body, stream);
23
44
  });
24
45
  }
25
46
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/routes/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAEhG,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAG/C,4FAA4F;AAC5F,MAAM,UAAU,mBAAmB,CAAC,GAAiB;IACnD,cAAc,CAAC,GAAG,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAClD,MAAM,SAAS,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAA;QACjF,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAC7C,MAAM,MAAM,GAAG,MAAM,CAAC;aACnB,GAAG,CAAC,WAAW,CAAC;aAChB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;QACzE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,CAAA;IAChC,CAAC,CAAC,CAAA;IAEF,cAAc,CAAC,GAAG,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACpD,MAAM,SAAS,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAA;QACjF,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAA;QACjF,OAAO,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC;YACzC,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE;YAC3B,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE;YAC7B,QAAQ;YACR,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM;SACzB,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,WAAW,CAAC,WAA+B,EAAE,KAAyB;IAC7E,KAAK,MAAM,SAAS,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAA;QAChC,IAAI,SAAS,KAAK,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,MAAM,IAAI,SAAS,EAAE,CAAC;YAC9F,OAAO,MAAM,CAAA;QACf,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC"}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/routes/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAEhG,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAE1D,4FAA4F;AAC5F,MAAM,UAAU,mBAAmB,CAAC,GAAiB;IACnD,cAAc,CAAC,GAAG,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAClD,MAAM,SAAS,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAA;QACjF,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAC7C,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACpC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CACjE,SAAS,CAAC,KAAK,CAAC,EAAE,EAClB,KAAK,EACL,KAAK,CACN,CAAA;QACD,4FAA4F;QAC5F,8FAA8F;QAC9F,6FAA6F;QAC7F,EAAE;QACF,8FAA8F;QAC9F,yFAAyF;QACzF,gCAAgC;QAChC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACvC,IAAI,eAAe,CAAC,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAA;YACvC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oCAAoC,EAAE;gBACtE,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE;gBAC3B,GAAG,EAAE,KAAK,CAAC,GAAG;aACf,CAAC,CAAA;YACF,OAAO,KAAK,CAAA;QACd,CAAC,CAAC,CAAA;QACF,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;IAEF,cAAc,CAAC,GAAG,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACpD,MAAM,SAAS,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAA;QACjF,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAA;QACjF,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC;YACvD,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE;YAC3B,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE;YAC7B,QAAQ;YACR,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM;SACzB,CAAC,CAAA;QACF,8FAA8F;QAC9F,6FAA6F;QAC7F,sEAAsE;QACtE,OAAO,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAC3C,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,WAAW,CAAC,WAA+B,EAAE,KAAyB;IAC7E,KAAK,MAAM,SAAS,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAA;QAChC,IAAI,SAAS,KAAK,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,MAAM,IAAI,SAAS,EAAE,CAAC;YAC9F,OAAO,MAAM,CAAA;QACf,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"lobby.d.ts","sourceRoot":"","sources":["../../src/routes/lobby.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAGhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAE3C;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAyBjE;AAED,4DAA4D;AAC5D,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CA0DjE"}
1
+ {"version":3,"file":"lobby.d.ts","sourceRoot":"","sources":["../../src/routes/lobby.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAIhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAE3C;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAgCjE;AAED,4DAA4D;AAC5D,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CA8DjE"}
@@ -1,5 +1,6 @@
1
1
  import { createMatchContract, getMatchContract, joinMatchContract, joinRunningMatchContract, kickPlayerContract, leaveMatchContract, listLobbiesContract, rejoinMatchContract, startMatchContract, takeoverVoteContract, updateMatchSettingsContract, } from '@chaos-overlords/contracts';
2
2
  import { NotFoundError } from '@chaos-overlords/kernel';
3
+ import { answering } from '../http/contractJson';
3
4
  import { requireMember } from '../http/guards';
4
5
  import { buildHonoRoute } from '../http/routes';
5
6
  /**
@@ -17,19 +18,26 @@ export function registerPublicLobbyRoutes(api) {
17
18
  reason: 'listing_disabled',
18
19
  });
19
20
  }
20
- return c.json({ matches: await kernel.query.listPublicLobbies(50) }, 200);
21
+ return c.json(answering(c, { matches: await kernel.query.listPublicLobbies(50) }), 200);
21
22
  });
22
23
  buildHonoRoute(api, createMatchContract, async (c) => {
23
24
  const membership = await c.get('container').kernel.lobby.createMatch(c.req.valid('json'));
24
- return c.json(membership, 201);
25
+ return c.json(answering(c, membership), 201);
25
26
  });
27
+ // Both join doors verify a password, so both hand the kernel the caller the attempt belongs to:
28
+ // its per-caller budget in front of PBKDF2 is what keeps one stranger from spending a match's.
29
+ // `rateLimited` put the key there; see `AppEnv`.
26
30
  buildHonoRoute(api, joinMatchContract, async (c) => {
27
- const membership = await c.get('container').kernel.lobby.join(c.req.valid('json'));
28
- return c.json(membership, 201);
31
+ const membership = await c
32
+ .get('container')
33
+ .kernel.lobby.join(c.req.valid('json'), c.get('caller'));
34
+ return c.json(answering(c, membership), 201);
29
35
  });
30
36
  buildHonoRoute(api, joinRunningMatchContract, async (c) => {
31
- const membership = await c.get('container').kernel.lobby.joinRunning(c.req.valid('json'));
32
- return c.json(membership, 201);
37
+ const membership = await c
38
+ .get('container')
39
+ .kernel.lobby.joinRunning(c.req.valid('json'), c.get('caller'));
40
+ return c.json(answering(c, membership), 201);
33
41
  });
34
42
  }
35
43
  /** The rest of the lobby lifecycle, for a seated member. */
@@ -37,7 +45,11 @@ export function registerMemberLobbyRoutes(api) {
37
45
  buildHonoRoute(api, getMatchContract, async (c) => {
38
46
  const principal = requireMember(c.get('principal'), c.req.valid('param').matchId);
39
47
  const view = await c.get('container').kernel.query.view(principal.match);
40
- return c.json({ match: view, joinCode: principal.match.joinCode, you: principal.player.id }, 200);
48
+ return c.json(answering(c, {
49
+ match: view,
50
+ joinCode: principal.match.joinCode,
51
+ you: principal.player.id,
52
+ }), 200);
41
53
  });
42
54
  buildHonoRoute(api, startMatchContract, async (c) => {
43
55
  await c
@@ -1 +1 @@
1
- {"version":3,"file":"lobby.js","sourceRoot":"","sources":["../../src/routes/lobby.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lobby.js","sourceRoot":"","sources":["../../src/routes/lobby.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/routes/protocol.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAEhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAE3C,+EAA+E;AAC/E,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAiB9D"}
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/routes/protocol.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAGhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAE3C,+EAA+E;AAC/E,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAiB9D"}
@@ -1,5 +1,6 @@
1
1
  import { handshakeContract, MULTIPLAYER_PROTOCOL_VERSION } from '@chaos-overlords/contracts';
2
2
  import { DomainError } from '@chaos-overlords/kernel';
3
+ import { answering } from '../http/contractJson';
3
4
  import { buildHonoRoute } from '../http/routes';
4
5
  /** The first call a game makes, before it sends or receives any match data. */
5
6
  export function registerProtocolRoutes(api) {
@@ -12,7 +13,7 @@ export function registerProtocolRoutes(api) {
12
13
  : 'This server is outdated and needs an update.';
13
14
  throw new DomainError('conflict', `Protocol version mismatch: client version ${clientVersion}, server version ${serverVersion}. ${action}`, { reason: 'protocol_version_mismatch', clientVersion, serverVersion });
14
15
  }
15
- return c.json({ protocolVersion: serverVersion }, 200);
16
+ return c.json(answering(c, { protocolVersion: serverVersion }), 200);
16
17
  });
17
18
  }
18
19
  //# sourceMappingURL=protocol.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/routes/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAA;AAC5F,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAG/C,+EAA+E;AAC/E,MAAM,UAAU,sBAAsB,CAAC,GAAiB;IACtD,cAAc,CAAC,GAAG,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACjD,MAAM,aAAa,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,eAAe,CAAA;QACzD,MAAM,aAAa,GAAG,4BAA4B,CAAA;QAClD,IAAI,aAAa,KAAK,aAAa,EAAE,CAAC;YACpC,MAAM,MAAM,GACV,aAAa,GAAG,aAAa;gBAC3B,CAAC,CAAC,6CAA6C;gBAC/C,CAAC,CAAC,8CAA8C,CAAA;YACpD,MAAM,IAAI,WAAW,CACnB,UAAU,EACV,6CAA6C,aAAa,oBAAoB,aAAa,KAAK,MAAM,EAAE,EACxG,EAAE,MAAM,EAAE,2BAA2B,EAAE,aAAa,EAAE,aAAa,EAAE,CACtE,CAAA;QACH,CAAC;QACD,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,eAAe,EAAE,aAAa,EAAE,EAAE,GAAG,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;AACJ,CAAC"}
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/routes/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAA;AAC5F,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAG/C,+EAA+E;AAC/E,MAAM,UAAU,sBAAsB,CAAC,GAAiB;IACtD,cAAc,CAAC,GAAG,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACjD,MAAM,aAAa,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,eAAe,CAAA;QACzD,MAAM,aAAa,GAAG,4BAA4B,CAAA;QAClD,IAAI,aAAa,KAAK,aAAa,EAAE,CAAC;YACpC,MAAM,MAAM,GACV,aAAa,GAAG,aAAa;gBAC3B,CAAC,CAAC,6CAA6C;gBAC/C,CAAC,CAAC,8CAA8C,CAAA;YACpD,MAAM,IAAI,WAAW,CACnB,UAAU,EACV,6CAA6C,aAAa,oBAAoB,aAAa,KAAK,MAAM,EAAE,EACxG,EAAE,MAAM,EAAE,2BAA2B,EAAE,aAAa,EAAE,aAAa,EAAE,CACtE,CAAA;QACH,CAAC;QACD,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC,EAAE,GAAG,CAAC,CAAA;IACtE,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"snapshots.d.ts","sourceRoot":"","sources":["../../src/routes/snapshots.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAGhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAE3C,uGAAuG;AACvG,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAqB9D"}
1
+ {"version":3,"file":"snapshots.d.ts","sourceRoot":"","sources":["../../src/routes/snapshots.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAIhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAE3C,uGAAuG;AACvG,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CA2B9D"}
@@ -1,4 +1,5 @@
1
1
  import { latestSnapshotContract, snapshotContract, uploadSnapshotContract, } from '@chaos-overlords/contracts';
2
+ import { answering } from '../http/contractJson';
2
3
  import { requireMember } from '../http/guards';
3
4
  import { buildHonoRoute } from '../http/routes';
4
5
  /** Native snapshots: the host's repair for a desynced turn, and the read every client resyncs from. */
@@ -11,12 +12,12 @@ export function registerSnapshotRoutes(api) {
11
12
  });
12
13
  buildHonoRoute(api, latestSnapshotContract, async (c) => {
13
14
  const principal = requireMember(c.get('principal'), c.req.valid('param').matchId);
14
- return c.json(await c.get('container').kernel.snapshots.latest(principal.match.id), 200);
15
+ return c.json(answering(c, await c.get('container').kernel.snapshots.latest(principal.match.id)), 200);
15
16
  });
16
17
  buildHonoRoute(api, snapshotContract, async (c) => {
17
18
  const principal = requireMember(c.get('principal'), c.req.valid('param').matchId);
18
19
  const { turn } = c.req.valid('param');
19
- return c.json(await c.get('container').kernel.snapshots.get(principal.match.id, turn), 200);
20
+ return c.json(answering(c, await c.get('container').kernel.snapshots.get(principal.match.id, turn)), 200);
20
21
  });
21
22
  }
22
23
  //# sourceMappingURL=snapshots.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshots.js","sourceRoot":"","sources":["../../src/routes/snapshots.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAG/C,uGAAuG;AACvG,MAAM,UAAU,sBAAsB,CAAC,GAAiB;IACtD,cAAc,CAAC,GAAG,EAAE,sBAAsB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACtD,MAAM,CAAC;aACJ,GAAG,CAAC,WAAW,CAAC;aAChB,MAAM,CAAC,SAAS,CAAC,MAAM,CACtB,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAC/D,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CACpB,CAAA;QACH,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC1B,CAAC,CAAC,CAAA;IAEF,cAAc,CAAC,GAAG,EAAE,sBAAsB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACtD,MAAM,SAAS,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAA;QACjF,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAA;IAC1F,CAAC,CAAC,CAAA;IAEF,cAAc,CAAC,GAAG,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAChD,MAAM,SAAS,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAA;QACjF,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QACrC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAA;IAC7F,CAAC,CAAC,CAAA;AACJ,CAAC"}
1
+ {"version":3,"file":"snapshots.js","sourceRoot":"","sources":["../../src/routes/snapshots.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAG/C,uGAAuG;AACvG,MAAM,UAAU,sBAAsB,CAAC,GAAiB;IACtD,cAAc,CAAC,GAAG,EAAE,sBAAsB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACtD,MAAM,CAAC;aACJ,GAAG,CAAC,WAAW,CAAC;aAChB,MAAM,CAAC,SAAS,CAAC,MAAM,CACtB,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAC/D,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CACpB,CAAA;QACH,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC1B,CAAC,CAAC,CAAA;IAEF,cAAc,CAAC,GAAG,EAAE,sBAAsB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACtD,MAAM,SAAS,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAA;QACjF,OAAO,CAAC,CAAC,IAAI,CACX,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAClF,GAAG,CACJ,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,cAAc,CAAC,GAAG,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAChD,MAAM,SAAS,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAA;QACjF,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QACrC,OAAO,CAAC,CAAC,IAAI,CACX,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,EACrF,GAAG,CACJ,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"turns.d.ts","sourceRoot":"","sources":["../../src/routes/turns.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAGhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAE3C,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CA0C1D"}
1
+ {"version":3,"file":"turns.d.ts","sourceRoot":"","sources":["../../src/routes/turns.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAIhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAE3C,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CA0C1D"}
@@ -1,4 +1,5 @@
1
1
  import { ownSubmissionContract, reportTurnContract, sealedOrdersContract, submitOrdersContract, } from '@chaos-overlords/contracts';
2
+ import { answering } from '../http/contractJson';
2
3
  import { requireMember } from '../http/guards';
3
4
  import { buildHonoRoute } from '../http/routes';
4
5
  /** The turn barrier: submit privately, read the sealed set, report the resulting hash. */
@@ -8,7 +9,7 @@ export function registerTurnRoutes(api) {
8
9
  const view = await c
9
10
  .get('container')
10
11
  .kernel.turns.submitOrders(requireMember(c.get('principal'), c.req.valid('param').matchId), turn, c.req.valid('json'));
11
- return c.json(view, 200);
12
+ return c.json(answering(c, view), 200);
12
13
  });
13
14
  buildHonoRoute(api, ownSubmissionContract, async (c) => {
14
15
  const principal = requireMember(c.get('principal'), c.req.valid('param').matchId);
@@ -16,7 +17,7 @@ export function registerTurnRoutes(api) {
16
17
  const view = await c
17
18
  .get('container')
18
19
  .kernel.query.ownSubmission(principal.match, principal.player.id, turn);
19
- return c.json(view, 200);
20
+ return c.json(answering(c, view), 200);
20
21
  });
21
22
  buildHonoRoute(api, sealedOrdersContract, async (c) => {
22
23
  const principal = requireMember(c.get('principal'), c.req.valid('param').matchId);
@@ -24,7 +25,7 @@ export function registerTurnRoutes(api) {
24
25
  const view = await c.get('container').kernel.query.sealedOrders(principal.match, turn);
25
26
  // A sealed set never changes, so clients and proxies may keep it.
26
27
  c.header('Cache-Control', 'private, max-age=31536000, immutable');
27
- return c.json(view, 200);
28
+ return c.json(answering(c, view), 200);
28
29
  });
29
30
  buildHonoRoute(api, reportTurnContract, async (c) => {
30
31
  const { turn } = c.req.valid('param');
@@ -1 +1 @@
1
- {"version":3,"file":"turns.js","sourceRoot":"","sources":["../../src/routes/turns.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"turns.js","sourceRoot":"","sources":["../../src/routes/turns.ts"],"names":[],"mappings":"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"}
@@ -3,10 +3,11 @@ import { type EventNotifier, type EventRepository, type EventStreamOpener, type
3
3
  * How many streams may be open at once, and against what.
4
4
  *
5
5
  * A stream is not a request: it lives until the client closes it, it holds a heartbeat timer and a
6
- * wake listener, and every event or heartbeat costs it one `listAfter` query. The
7
- * per-player rate limit counts the opening call and nothing after it, so without these one
8
- * authenticated member could hold thousands of streams and turn each published event into thousands
9
- * of database reads and thousands of response writes — the whole match stops sealing for everybody.
6
+ * wake listener, and it is written to for every event of its match. The per-player rate limit counts
7
+ * the opening call and nothing after it, so without these one authenticated member could hold
8
+ * thousands of streams and turn each published event into thousands of response writes — the whole
9
+ * match stops sealing for everybody. (What one event costs in READS is `MatchLog`'s business, and
10
+ * the answer there is "once for the match", not once per stream.)
10
11
  *
11
12
  * `perPlayer` is generous enough for the one case a healthy client produces: a reconnect whose
12
13
  * predecessor is still being torn down. Reaching it closes that player's oldest stream rather than
@@ -27,10 +28,21 @@ export declare class LocalEventHub implements EventNotifier, EventStreamOpener,
27
28
  private readonly events;
28
29
  private readonly heartbeatMs;
29
30
  private readonly limits;
31
+ /** Told about a stored event a stream had to skip, so an operator can find out it exists. */
32
+ private readonly onUnreadable?;
30
33
  /** Insertion-ordered, which is what makes "close this player's oldest" a first match. */
31
34
  private readonly listeners;
35
+ /**
36
+ * The shared read and shared frames of each match with a stream open; see `MatchLog`.
37
+ *
38
+ * Keyed by match and dropped with the last stream of it, so what this holds is bounded by the
39
+ * stream caps rather than by how many matches the server has ever served.
40
+ */
41
+ private readonly logs;
32
42
  private open_;
33
- constructor(events: EventRepository, heartbeatMs: number, limits?: EventHubLimits);
43
+ constructor(events: EventRepository, heartbeatMs: number, limits?: EventHubLimits,
44
+ /** Told about a stored event a stream had to skip, so an operator can find out it exists. */
45
+ onUnreadable?: ((matchId: string, seq: number) => void) | undefined);
34
46
  notify(event: PersistedEvent): Promise<void>;
35
47
  /** Wake every stream of a match; used when the notification arrives without the event body. */
36
48
  wake(matchId: string): void;
@@ -45,6 +57,15 @@ export declare class LocalEventHub implements EventNotifier, EventStreamOpener,
45
57
  matchId: string;
46
58
  playerId: string;
47
59
  }): Promise<void>;
60
+ /**
61
+ * End every stream this process holds, for a graceful shutdown.
62
+ *
63
+ * An event stream never ends on its own, so `server.close()` cannot return while one is open.
64
+ * Ending them here is what lets a SIGTERM finish at once instead of waiting out the grace period
65
+ * and then cutting the sockets, which clients see as a reset rather than as a stream to resume
66
+ * from their `Last-Event-ID`.
67
+ */
68
+ closeAll(): void;
48
69
  connectionCount(matchId: string): number;
49
70
  /** Streams open across every match in this process. */
50
71
  get openStreams(): number;
@@ -54,15 +75,20 @@ export declare class LocalEventHub implements EventNotifier, EventStreamOpener,
54
75
  afterSeq: number;
55
76
  signal: AbortSignal;
56
77
  }): Promise<Response>;
78
+ private logOf;
57
79
  private subscribe;
58
80
  /**
59
81
  * Enforce the three caps before a stream is built.
60
82
  *
61
- * The process cap is checked first: it is the one that protects everyone else's matches, and a
62
- * refusal is cheaper than closing somebody's live stream to make room for a caller this cap is
63
- * about to turn away anyway. The caller's own stale streams go next, BEFORE the match cap is
64
- * read: a full match is exactly the state a reconnecting player finds when every seat holds its
65
- * quota, and refusing them there would turn the one legitimate reconnect into a 429.
83
+ * The caller's own stale streams are closed FIRST, before either ceiling is read. Closing them is
84
+ * not a concession to the caller, it is bookkeeping: a reconnect whose predecessor has not
85
+ * finished being torn down is the one case that reaches these caps in healthy traffic, and the
86
+ * corpse it is replacing occupies a slot in all three counts. Reading the process cap ahead of
87
+ * that answered 429 to the player whose laptop had just woken up, on a server whose own count
88
+ * would have been under the cap the moment their dead stream went.
89
+ *
90
+ * `perMatch` and `perProcess` then refuse whatever is still over, which is the case no client can
91
+ * talk its way past.
66
92
  */
67
93
  private makeRoom;
68
94
  }
@@ -1 +1 @@
1
- {"version":3,"file":"LocalEventHub.d.ts","sourceRoot":"","sources":["../../src/sse/LocalEventHub.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAEnB,KAAK,YAAY,EAClB,MAAM,yBAAyB,CAAA;AAKhC;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,eAAO,MAAM,wBAAwB,EAAE,cAItC,CAAA;AAQD;;;GAGG;AACH,qBAAa,aAAc,YAAW,aAAa,EAAE,iBAAiB,EAAE,YAAY;IAMhF,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPzB,yFAAyF;IACzF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IACjE,OAAO,CAAC,KAAK,CAAI;gBAGE,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,MAAM,EACnB,MAAM,GAAE,cAAyC;IAG9D,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD,+FAA+F;IAC/F,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI3B;;;;;;OAMG;IACG,KAAK,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxE,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAIxC,uDAAuD;IACvD,IAAI,WAAW,IAAI,MAAM,CAExB;IAEK,IAAI,CAAC,KAAK,EAAE;QAChB,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,CAAA;QAChB,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,WAAW,CAAA;KACpB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAWrB,OAAO,CAAC,SAAS;IAkBjB;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAQ;CAmBjB"}
1
+ {"version":3,"file":"LocalEventHub.d.ts","sourceRoot":"","sources":["../../src/sse/LocalEventHub.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAEnB,KAAK,YAAY,EAClB,MAAM,yBAAyB,CAAA;AAIhC;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,eAAO,MAAM,wBAAwB,EAAE,cAItC,CAAA;AAQD;;;GAGG;AACH,qBAAa,aAAc,YAAW,aAAa,EAAE,iBAAiB,EAAE,YAAY;IAahF,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,6FAA6F;IAC7F,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IAhBhC,yFAAyF;IACzF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IACjE;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA8B;IACnD,OAAO,CAAC,KAAK,CAAI;IAEjB,YACmB,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,MAAM,EACnB,MAAM,GAAE,cAAyC;IAClE,6FAA6F;IAC5E,YAAY,CAAC,GAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,aAAA,EACpE;IAEE,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAMjD;IAED,+FAA+F;IAC/F,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAI1B;IAED;;;;;;OAMG;IACG,KAAK,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvE;IAED;;;;;;;OAOG;IACH,QAAQ,IAAI,IAAI,CAOf;IAED,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvC;IAED,uDAAuD;IACvD,IAAI,WAAW,IAAI,MAAM,CAExB;IAEK,IAAI,CAAC,KAAK,EAAE;QAChB,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,CAAA;QAChB,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,WAAW,CAAA;KACpB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAgBpB;IAED,OAAO,CAAC,KAAK;IAQb,OAAO,CAAC,SAAS;IAuBjB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,QAAQ;CAmBjB"}
@@ -1,7 +1,7 @@
1
1
  import { LIMITS } from '@chaos-overlords/contracts';
2
2
  import { RateLimitedError, } from '@chaos-overlords/kernel';
3
3
  import { createSseResponse } from './createSseResponse';
4
- const PAGE_SIZE = 200;
4
+ import { MatchLog } from './MatchLog';
5
5
  export const DEFAULT_EVENT_HUB_LIMITS = {
6
6
  perPlayer: 3,
7
7
  perMatch: LIMITS.maxPlayers * 3,
@@ -15,19 +15,36 @@ export class LocalEventHub {
15
15
  events;
16
16
  heartbeatMs;
17
17
  limits;
18
+ onUnreadable;
18
19
  /** Insertion-ordered, which is what makes "close this player's oldest" a first match. */
19
20
  listeners = new Map();
21
+ /**
22
+ * The shared read and shared frames of each match with a stream open; see `MatchLog`.
23
+ *
24
+ * Keyed by match and dropped with the last stream of it, so what this holds is bounded by the
25
+ * stream caps rather than by how many matches the server has ever served.
26
+ */
27
+ logs = new Map();
20
28
  open_ = 0;
21
- constructor(events, heartbeatMs, limits = DEFAULT_EVENT_HUB_LIMITS) {
29
+ constructor(events, heartbeatMs, limits = DEFAULT_EVENT_HUB_LIMITS,
30
+ /** Told about a stored event a stream had to skip, so an operator can find out it exists. */
31
+ onUnreadable) {
22
32
  this.events = events;
23
33
  this.heartbeatMs = heartbeatMs;
24
34
  this.limits = limits;
35
+ this.onUnreadable = onUnreadable;
25
36
  }
26
37
  async notify(event) {
38
+ // The notification carries the durable row, so its frame is formatted once here and every
39
+ // stream one event behind — which is every healthy stream of the match — is served from it
40
+ // without reading anything. See `MatchLog`.
41
+ this.logs.get(event.matchId)?.record(event);
27
42
  this.wake(event.matchId);
28
43
  }
29
44
  /** Wake every stream of a match; used when the notification arrives without the event body. */
30
45
  wake(matchId) {
46
+ // Snapshot deliberately: waking a stream can close it, which mutates the set being walked.
47
+ // oxlint-disable-next-line unicorn/no-useless-spread
31
48
  for (const subscription of [...(this.listeners.get(matchId) ?? [])])
32
49
  subscription.wake();
33
50
  }
@@ -39,11 +56,30 @@ export class LocalEventHub {
39
56
  * (which names each player's state hash) and every host change until they choose to disconnect.
40
57
  */
41
58
  async close(input) {
59
+ // Snapshot deliberately: `close()` removes the subscription from the set being walked.
60
+ // oxlint-disable-next-line unicorn/no-useless-spread
42
61
  for (const subscription of [...(this.listeners.get(input.matchId) ?? [])]) {
43
62
  if (subscription.playerId === input.playerId)
44
63
  subscription.close();
45
64
  }
46
65
  }
66
+ /**
67
+ * End every stream this process holds, for a graceful shutdown.
68
+ *
69
+ * An event stream never ends on its own, so `server.close()` cannot return while one is open.
70
+ * Ending them here is what lets a SIGTERM finish at once instead of waiting out the grace period
71
+ * and then cutting the sockets, which clients see as a reset rather than as a stream to resume
72
+ * from their `Last-Event-ID`.
73
+ */
74
+ closeAll() {
75
+ // Snapshot deliberately: `close()` removes the subscription from the set being walked.
76
+ // oxlint-disable-next-line unicorn/no-useless-spread
77
+ for (const subscriptions of [...this.listeners.values()]) {
78
+ // oxlint-disable-next-line unicorn/no-useless-spread
79
+ for (const subscription of [...subscriptions])
80
+ subscription.close();
81
+ }
82
+ }
47
83
  connectionCount(matchId) {
48
84
  return this.listeners.get(matchId)?.size ?? 0;
49
85
  }
@@ -53,10 +89,25 @@ export class LocalEventHub {
53
89
  }
54
90
  async open(input) {
55
91
  this.makeRoom(input.matchId, input.playerId);
92
+ const log = this.logOf(input.matchId);
56
93
  return createSseResponse({
57
- listAfter: (afterSeq) => this.events.listAfter(input.matchId, afterSeq, PAGE_SIZE),
94
+ page: (afterSeq, force) => log.page(afterSeq, force),
95
+ caughtUp: (lastSeq) => log.caughtUp(lastSeq),
58
96
  subscribe: (wake, close) => this.subscribe(input.matchId, input.playerId, wake, close),
59
- }, { afterSeq: input.afterSeq, heartbeatMs: this.heartbeatMs, signal: input.signal });
97
+ }, {
98
+ afterSeq: input.afterSeq,
99
+ heartbeatMs: this.heartbeatMs,
100
+ signal: input.signal,
101
+ onUnreadable: (seq) => this.onUnreadable?.(input.matchId, seq),
102
+ });
103
+ }
104
+ logOf(matchId) {
105
+ const existing = this.logs.get(matchId);
106
+ if (existing)
107
+ return existing;
108
+ const log = new MatchLog(matchId, this.events);
109
+ this.logs.set(matchId, log);
110
+ return log;
60
111
  }
61
112
  subscribe(matchId, playerId, wake, close) {
62
113
  const set = this.listeners.get(matchId) ?? new Set();
@@ -68,32 +119,40 @@ export class LocalEventHub {
68
119
  if (!set.delete(subscription))
69
120
  return;
70
121
  this.open_ -= 1;
71
- if (set.size === 0)
122
+ if (set.size === 0) {
72
123
  this.listeners.delete(matchId);
124
+ // Nothing reads this match any more, so its frames are only memory. The next stream of it
125
+ // starts from the log, which is where the truth was all along.
126
+ this.logs.delete(matchId);
127
+ }
73
128
  };
74
129
  }
75
130
  /**
76
131
  * Enforce the three caps before a stream is built.
77
132
  *
78
- * The process cap is checked first: it is the one that protects everyone else's matches, and a
79
- * refusal is cheaper than closing somebody's live stream to make room for a caller this cap is
80
- * about to turn away anyway. The caller's own stale streams go next, BEFORE the match cap is
81
- * read: a full match is exactly the state a reconnecting player finds when every seat holds its
82
- * quota, and refusing them there would turn the one legitimate reconnect into a 429.
133
+ * The caller's own stale streams are closed FIRST, before either ceiling is read. Closing them is
134
+ * not a concession to the caller, it is bookkeeping: a reconnect whose predecessor has not
135
+ * finished being torn down is the one case that reaches these caps in healthy traffic, and the
136
+ * corpse it is replacing occupies a slot in all three counts. Reading the process cap ahead of
137
+ * that answered 429 to the player whose laptop had just woken up, on a server whose own count
138
+ * would have been under the cap the moment their dead stream went.
139
+ *
140
+ * `perMatch` and `perProcess` then refuse whatever is still over, which is the case no client can
141
+ * talk its way past.
83
142
  */
84
143
  makeRoom(matchId, playerId) {
85
- if (this.open_ >= this.limits.perProcess) {
86
- throw new RateLimitedError('This server is holding as many event streams as it can', {
87
- reason: 'too_many_streams',
88
- scope: 'process',
89
- });
90
- }
91
144
  const set = this.listeners.get(matchId);
92
145
  if (set) {
93
146
  const mine = [...set].filter((subscription) => subscription.playerId === playerId);
94
147
  for (const stale of mine.slice(0, mine.length - this.limits.perPlayer + 1))
95
148
  stale.close();
96
149
  }
150
+ if (this.open_ >= this.limits.perProcess) {
151
+ throw new RateLimitedError('This server is holding as many event streams as it can', {
152
+ reason: 'too_many_streams',
153
+ scope: 'process',
154
+ });
155
+ }
97
156
  if ((this.listeners.get(matchId)?.size ?? 0) >= this.limits.perMatch) {
98
157
  throw new RateLimitedError('This match is holding as many event streams as it can', {
99
158
  reason: 'too_many_streams',
@@ -1 +1 @@
1
- {"version":3,"file":"LocalEventHub.js","sourceRoot":"","sources":["../../src/sse/LocalEventHub.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LocalEventHub.js","sourceRoot":"","sources":["../../src/sse/LocalEventHub.ts"],"names":[],"mappings":"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"}