Skip to content

fix: api event-dedup ordering, news stream errors, redis parse guard (#532, #546, part of #557)#351

Open
Flegma wants to merge 2 commits into
mainfrom
audit/api-reliability
Open

fix: api event-dedup ordering, news stream errors, redis parse guard (#532, #546, part of #557)#351
Flegma wants to merge 2 commits into
mainfrom
audit/api-reliability

Conversation

@Flegma

@Flegma Flegma commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Three self-contained reliability fixes from the 2026-07 audit. Closes #532, #546; partially addresses #557.

Changes

Match-event dedup ordering (#532)
MatchEventsGateway.handleMatchEvent wrote the dedup cache entry before running the processor, so a transient processor failure (for example a Hasura hiccup) left a "processed" marker that suppressed the game server's redelivery for the 10s TTL, silently dropping the event. The entry is now written only after process() resolves, and processing is wrapped in try/catch that logs with the stack and rethrows (so redelivery reprocesses). Affects every event type.

News image stream (#546)
NewsController.serveImage piped the S3 stream to the response with no handlers. An upstream stream error threw an unhandled 'error' event (crashing the pod), and a client disconnecting mid-download left the upstream stream open (fd leak). Added an error handler (log + 500/destroy) and a response close handler that destroys the stream.

Redis pub/sub parse guard (#557, one half)
SocketsService called JSON.parse on every broadcast-message / send-message-to-steam-id payload inside the sub.on("message") listener with no guard, so a malformed message was an uncaught exception in an event handler (pod crash). Now wrapped in try/catch that logs and returns.

Testing

  • tsc --noEmit: no new errors (the 19 pre-existing errors are all in src/matchmaking/matchmake.service.spec.ts, tracked as #534).
  • New match-events.gateway.spec.ts (3 tests): dedup entry written only after success, not written on failure (so redelivery retries), and dedup short-circuit skips processing. Passing.

Deferred from this PR (need a decision, documented on the issues)

  • #557 bake-controller auth: x-origin-auth === nodeId is tautological because nodeId is a public path param. Fixing it needs a real per-node shared secret (same class as the connector auth gap and #413), so it is not a self-contained change.
  • #533 (migration runner content hash) and #534 (spec files excluded from CI typecheck + the 19 resulting errors) are real but out of scope here: #533 changes the deploy-critical migration path and #534 is a CI-config change plus a spec cleanup. Left for their own PRs.

Flegma added 2 commits July 10, 2026 21:58
…e guard

- MatchEventsGateway: write the dedup cache entry only after the processor
  succeeds, and wrap processing in try/catch that logs and rethrows. A
  transient failure no longer both throws and leaves a 'processed' marker
  that suppresses the game server's redelivery for the 10s TTL (#532).
- NewsController.serveImage: handle 'error' on the S3 stream and destroy it
  on response close, so a stream error can't crash the process and a client
  disconnect can't leak the upstream fd (#546).
- SocketsService: guard JSON.parse of pub/sub messages so a malformed
  payload logs and returns instead of throwing an uncaught exception in the
  message listener (#557, redis-handler half).

Adds match-events.gateway.spec.ts covering the dedup ordering.
…ollow-up)

JSON.parse succeeds for a valid non-object payload (e.g. literal null, which
typeof-reports as object), so the destructure sat outside the try and would
throw an uncaught TypeError. Validate parsed is a non-null object first.
@Flegma

Flegma commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

Independent code review run on the diff. It caught that the redis parse guard wrapped only JSON.parse, but JSON.parse("null") returns null without throwing and the destructure sat outside the try, so a valid non-object payload would still crash the pod. Fixed in 9865bee with a non-object guard. The review confirmed the match-events dedup rethrow and the news stream error/close handlers are correct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant