Skip to content

Tournament-scoped SSE nudges - #307

Merged
amrtgaber merged 1 commit into
mainfrom
sse-tournament-scoping
Jul 26, 2026
Merged

Tournament-scoped SSE nudges#307
amrtgaber merged 1 commit into
mainfrom
sse-tournament-scoping

Conversation

@amrtgaber

Copy link
Copy Markdown
Contributor

Summary

Implements #293 via the issue's preferred design: nudges stay one global stream on the existing single connection, but each nudge's payload now says which tournaments it concerns, so a client watching one tournament can skip refetches another tournament's poll cycle caused. Fully backward compatible — null (or ignoring the field) means "refetch", exactly the pre-#293 behavior.

Plumbing (worker → table → poll loop → SSE frame):

  • nudge_versions.tournament_ids — nullable JSON column (expand-only migration 62ef856f3e47, validated on a throwaway Postgres 16; NULL = unscoped, so mixed-revision rollover is safe).
  • emit_nudge(..., tournament_ids=…) stores a deduped, sorted scope inside the same transaction as the data write; poll_for_nudges republishes it; the SSE frame payload becomes {"polled_at": …, "tournament_ids": [...] | null}.
  • New get_tournament_ids_for_profiles roster helper resolves a profile set to the tournaments rostering them.

Per-tick scoping (emit cadence unchanged — no freshness regression):

  • player_stats → tournaments whose rosters contain the polled batch (the batch is the cross-tournament union, so this is every tournament with a linked tracked entrant — tournaments with empty or unlinked rosters stop waking clients).
  • recent_matches → tournaments of the profiles whose fetch succeeded this cycle (a failed profile contributed no write).
  • live_matches → tournaments of the previous live set ∪ the new one, with the previous set read before the wholesale rewrite — so a tournament whose entrant just left a game still gets its in_match flip.

README's third-party-frontend section documents the payload contract for consumers.

Tests

585 passed. New: roster-helper mapping (shared profile across tournaments, unknown/empty inputs); scoped + unscoped SSE frame rendering; emit→poll→hub round-trip carrying a deduped sorted scope and None (integration, real Postgres); a two-tournament tick test proving the standings nudge carries only the rostered tournament's id. Existing event/stream/tick tests pass unchanged.

Closes #293

@amrtgaber
amrtgaber merged commit 6125dc7 into main Jul 26, 2026
3 checks passed
@amrtgaber
amrtgaber deleted the sse-tournament-scoping branch July 26, 2026 02:57
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.

Tournament-scoped SSE nudges for concurrent live events

1 participant