Documentation Index
Fetch the complete documentation index at: https://285e39fd5e337e58f16290.sightscreen.app/llms.txt
Use this file to discover all available pages before exploring further.
How it works
The live score pipeline is fully event-driven. There is no monolithic job — instead, a chain of specialized components each do one thing.Two pollers, two cadences
| Poller | Cadence | Data | Matches |
|---|---|---|---|
| ScorePoller (Poller 1) | 5 seconds | Scores, batting/bowling stats, match status | All live matches |
| MarqueePoller (Poller 2) | 2.5 seconds | Everything above + ball-by-ball data | Current marquee league only |
ScorePoller class. The marquee poller fetches the balls include from SportMonks, which provides ball-by-ball data needed for Tier1 event detection (sixes, fours, maidens, hat-tricks).
For non-marquee matches, only Tier0 (score-based) events are detected.
MatchEventBus: the detection pipeline
The EventBus receives raw match data and runs it through a four-stage detection pipeline:Tier0EventDetector (score-based)
Compares current scores against previous scores stored in
active-matches. Detects: match_end, innings_end, hundred, batsman_on_90s, fifty, batsman_on_fire, bowler_on_fire, wicket, new_batsman.Tier1EventDetector (ball-based)
Analyzes the last 30 balls stored in
active-matches. Detects: hattrick, on_hattrick, consecutive_sixes, maiden, six, four. Only runs for marquee league matches (requires ball data).CooldownFilter
Suppresses duplicate events using a cooldowns map stored on the
active-matches record. For example, a fifty event for the same batsman won’t fire again within the cooldown window.pickBestEvent priority-sorts all remaining candidates and selects the single highest-priority event as the keyEvent.
Event priorities and alert worthiness
Events are sorted by priority (lower number = higher priority):| Priority | Event | Alert worthy? |
|---|---|---|
| P1 | match_end | Yes (P10 push) |
| P2 | innings_end | Yes |
| P3 | hattrick | Yes |
| P4 | on_hattrick | Yes |
| P5 | hundred | Yes |
| P6 | batsman_on_90s | Yes |
| P7 | consecutive_sixes | Yes |
| P8 | fifty | Yes |
| P9 | batsman_on_fire | Yes |
| P10 | bowler_on_fire | Yes |
| P11 | wicket | Yes |
| P12 | new_batsman | Yes |
| P13 | maiden | Yes |
| P14 | six | No (P5 silent) |
| P15 | four | No (P5 silent) |
Alert-worthy events are sent as P10 (high priority) APNs pushes that wake the screen and show a banner. Non-alert events (six, four) are sent as P5 (silent) pushes that update the Live Activity without disturbing the user.
DisplayStateBuilder
DisplayStateBuilder takes the raw match data and the selected keyEvent and builds a UnifiedDisplayState. This is the single payload shape that iOS renders on the Lock Screen and Dynamic Island. It includes: team names, scores, overs, batting/bowling stats, recent balls, run rate, chase info, and the key event label.
LACoordinator: fan-out to devices
TheLACoordinator listens for MatchBusEvent emissions from the EventBus:
- Queries
live-activitiestable for all records withmatchIdandstatus=active - Builds a single APNs payload from the
UnifiedDisplayState - Sets push priority based on
isAlertWorthy(P10 or P5) - Calls
sendBatchviaApnsDeliveryServicefor all tokens - Handles invalid token responses by marking records as
status=ended, endReason=token_invalid
Resilience
Circuit breaker
The SportMonks client uses cockatiel for circuit breaking. If the API returns repeated 5xx errors, the circuit opens and requests are short-circuited for a cooldown period. This prevents hammering a degraded upstream.Distributed locking
Each poller acquires a distributed lock before polling to prevent duplicate processing when multiple backend instances are running. If the lock is held by another instance, the poller skips that cycle.Key tables
| Table | Key schema | Purpose |
|---|---|---|
active-matches | PK: matchId | Tracks polling state, previous scores, cooldown map, last 30 balls |
live-activities | PK: matchId, SK: userId#deviceId | Maps users + devices to active LA tokens |
Related pages
- Live Activity lifecycle — how LAs are created, updated, and ended
- Match following — what triggers the LA creation that feeds into this pipeline
- Device registration — how push tokens get registered in the first place