The first scheduled run of #1157's workflows failed outright: a server
started a chunked HTTP response and then hung up mid-chunk, which
urllib surfaces as http.client.IncompleteRead - a subclass of
http.client.HTTPException, not of OSError/URLError/ValueError, so
probe()'s except clause let it propagate and took the whole run down
before it wrote anything to --json, including check_channels_fast.yml's
run.jsonl.
Catch http.client.HTTPException alongside the existing exceptions and
treat it as unreachable, same as any other broken connection. Verified
against the exact exception (mocked) and against the live lists.
Builds on the idea in #1145 (a checker that maps failures back to a channel
and list, and tells a geo-blocked channel from a dead one) with a few
additions:
check_channels.py
- Standard library only, same as #1145's version.
- Adds a `disputed` state: an optional --confirm-dead pass gives ffprobe a
second opinion on anything that looks dead over HTTP, before it gets
reported as dead. This is one-directional (can only pull a verdict out
of `dead`, never push one into it) because ffprobe itself is not
reliable enough to trust in the other direction - a known-good DASH
channel needed longer than any sane per-channel budget to open while
testing this, and a header check alone had already been fooled by an
isolated media fragment sitting at a URL that looked like a live channel
(a mistake made and caught while triaging #1149/#1151 - see the
docstring for the details).
- Restructured to share one worker pool across every list in a run
instead of a fresh pool per list, which stopped small lists from paying
the same wall-clock floor as large ones; a full run across all lists
dropped from not finishing in 15 minutes to about 10.
- --json writes one record per channel per run, for building a history.
generate_dashboard.py
- Turns that history into a single self-contained docs/index.html: current
state breakdown, an alive-share trend across every run kept, a per-list
breakdown, and a searchable/filterable table of everything that is not
currently alive.
Two new scheduled workflows
- check_channels_fast.yml: every 6 hours, HTTP checks only.
- check_channels_deep.yml: every 2 days, with --confirm-dead (needs ffmpeg).
Both append to .github/checker-history/history.jsonl (pruned to 90 days),
then build and deploy the dashboard to GitHub Pages.