Match Listeners¶
The page at /admin/match-listeners (nav: Advanced → Match Listeners) lists
match_listeners lifecycle rows grouped by match. Layout matches the
Matches board: a left filter sidebar and card groups in the
main column.
Filters (sidebar)¶
- Scheduled day —
admin_day_range/AdminDayRange(presets: Today, Yesterday, Last 5 days, Custom) - League — server filter (reloads list)
- Search — client-side text filter on loaded groups
- Min runs — server filter (
min_runs) - Test matches — Any / Test only / Live only (
Match.is_test, client-side)
Changing day, league, or min runs reloads via
GET /api/match-listeners?league=&scheduled_from=&scheduled_to=&min_runs=. Search and test
filters only hide already-loaded groups.
Deep-link from Matches (listener badges / Listener state):
?match_id=&day=&league=. Day and league apply before the first load; Search
is set to the match id when that group is present. If the match has no listener
runs for the selected day/league (min_runs ≥ 1), a toast explains that and
the page stays in its normal loaded state.
Match naming¶
Same convention as Matches:
| Field | Form | Use |
|---|---|---|
display_title |
Full market + team name | Card headline |
display_label |
Team aliases (AWAY @ HOME) |
Subtitle, pickers |
On each card, internal match id and Sportradar match id show the first 8 characters (full value on hover; copy icon copies the full UUID). Shortcode has a copy icon as well.
Operators can load a run’s text log (copy to clipboard), download the
per-run .log or the match event .json recording, and open Actions →
Celery task… for Postgres-stored Celery ids (run
match_listeners.celery_task_id and match
listener_start_settings.celery_task_id) with copy and Flower deep links when
Flower is configured.
This page lists match_listeners lifecycle rows. Start listener enqueues
start_match_listener with force=true (fresh Celery task id; prefer Stop
first if a run is live). Test-match starts follow the clone/listen env gate
(hidden in main); live matches can start in any environment. Stop listener
revokes Celery tasks, closes open runs, clears Redis start barriers, and turns
auto-dispatch off for that match. Clone flows remain on
Clone Past Match.
For badges, exit codes, hard fail vs stop, and “will Beat restart?”: Lifecycle cases.
Operator workflow¶
- Open
/admin/match-listeners. - Set day / league / min runs in the sidebar, then review groups.
- Optionally use Search or Test matches to narrow in the browser.
- On a match card: Start listener (confirm) to force-enqueue a new start, or Stop listener (confirm) to revoke/close and turn auto-dispatch off. On a run: Load log / Copy log, Download log, Download events, or Celery task… (stored task ids + Flower).
Data sources¶
| Surface | Source |
|---|---|
| List | GET /api/match-listeners?league=&scheduled_from=&scheduled_to=&match_id=&min_runs= |
| Start | POST /api/matches/{match_id}/start-listener with { "force": true } |
| Stop | POST /api/matches/{match_id}/stop-listener |
| Log preview | GET /api/match-listeners/{id}/log |
| Download log | GET /api/match-listeners/{id}/log/download |
| Download events | GET /api/match-listeners/{id}/events/download |
| Live write (listener host) | {FILESYSTEM_CONTAINER_DATA_DIR}/listener/{league}/{shortcode}.json (+ optional .log) |
| Archive (downloads / replay) | S3 AWS_S3_MATCH_ARCHIVE_BUCKET keys {shortcode}.json and {shortcode}.{listener_id[:8]}.log when Match.listener_events_archived |
shortcode is {sr_id[:8]}-{internal_match_id[:8]} (Sportradar match id +
internal match id). Many runs have no text log: listener_write_logs_to_file
defaults to false unless overridden at start (Clone Past Match turns it on).
Event recordings are per match (shared across runs), not per listener row.
Admin Download log / events and log preview read from the S3 gamedata
archive only (no local filesystem fallback). They require
Match.listener_events_archived=true after a successful archive upload (on
listener exit and via the sweep_pending_listener_archives beat task, which
runs every 5 minutes and
which enqueues per-match archive_match_listener_data jobs for terminal
matches scheduled within a lookback window (default 48 hours; override via
lookback_hours on the sweep task). The sweep only considers matches that
had at least one closed listener run with event recording enabled
(listener_write_events_to_file true or unset; Clone Past Match defaults it
off, so those runs are not sticky-retried).
Only staging/main archive to S3 — develop/test keep recordings on disk;
download/replay of archived matches is a staging/main path.
Incomplete / unclosed JSON arrays are never uploaded.
Admin day presets convert browser-local calendar days to UTC scheduled_from/scheduled_to.
Status badges and lifecycle cases¶
| Status | Meaning |
|---|---|
| Running | Open row with a recent heartbeat |
| Stale | Open row with a stale heartbeat (until Beat sweeper / dispatch abandon) |
| Abandoned | Closed exit 14 after heartbeat timeout (hard fail; barriers cleared if no active sibling; dispatch may re-enqueue) |
| Stopped | Closed exit 15 (operator Stop; auto-dispatch off) |
| Ended | Closed for any other reason (graceful end, failure exit, unexpected cancel 16) |
Stop turns off auto_dispatch_listener. Abandoned leaves it on and
clears Redis barriers so Beat can recover. Start is disabled while a run
is Running (stop first); test-match starts remain env-gated.
Full case list (start, skip, failure, hard kill, stop, dispatch off): Match listener startup — Lifecycle cases.
Use the ? next to each run’s exit code (and on the expanded Exit code
row) for the operator catalog of codes (0 / 9–16). Same tables live in
Exit codes.
Hard stop vs Abandoned¶
See the lifecycle case catalog (hard kill → Stale → Abandoned vs operator Stop). Short form: abandon recovers via dispatch; stop blocks auto re-enqueue.
Details: Correcting a hard-failed listener.
Related¶
- Matches — browse matches / delete test clones
- Clone Past Match
- Match listener startup — Beat flow + lifecycle cases