CDN probe: skip while idle, back off while degraded

The 3-min 64KB video download ran on a timer regardless of whether
anyone was using the app — wasteful upstream bandwidth, and pure churn
while the CDN 403s our IP. Now: no fetch while no stream has been
requested in 15 min (api_stream bumps _LAST_PLAY), and 30-min retry
while DEGRADED. Pill state goes stale while idle, which is fine — the
next viewer's own request is the true signal, and the probe resumes
within a minute of it.
This commit is contained in:
jozamudi committed 2026-09-29 17:23:18 +00:00
1 parent 0cd79dd701
commit 1154203569
1 file changed
+17 -4
+17 -4
View File
@@ -49,8 +49,15 @@ VERSION = _version()
# app.js uses the same value as these stats. Change here only.
DONE_RATIO = 0.95
# latest probe result + last 20 samples (~1h at 3-min spacing), for GET /api/cdn
# latest probe result + last 20 samples, for GET /api/cdn
_CDN = {"state": "unknown", "kbps": 0.0, "ts": 0.0, "hist": []}
# ponytail: probe only when someone is around to care — skip the 64 KB video
# download while the app has been idle (no stream requested in 15 min), and
# back off to 30 min while DEGRADED (re-hitting a blocked CDN every 3 min is
# just churn). api_stream() bumps _LAST_PLAY.
_LAST_PLAY = 0.0
_IDLE_SECS = 900
_DEGRADED_RETRY = 1800
# origin (primary provider pages/API) health — separate host, separate failure
# mode (observed 2026-09-03: CDN fine while origin 503'd "Under Maintenance")
_ORIGIN = {"state": "unknown", "msg": "", "ts": 0.0, "hist": []}
@@ -60,8 +67,9 @@ _CDN_THRESHOLD = float(os.environ.get("ANIWEB_CDN_KBPS", "40"))
def _cdn_probe():
"""Background probe: pull 64KB from the CDN every 3 min and log state
flips, so server.log shows when a degraded window ends (CDN RECOVERED).
"""Background probe: pull 64KB from the CDN and log state flips, so
server.log shows when a degraded window ends (CDN RECOVERED). Skipped
while the app is idle and backed off while DEGRADED (see _LAST_PLAY).
Probe target: ep_id 1 = One Piece E1 on the primary provider.
ponytail: single fixed episode; if it ever disappears, the probe logs
DEGRADED forever — swap the ID, don't build a picker."""
@@ -72,6 +80,9 @@ def _cdn_probe():
state = None
while True:
if time.time() - _LAST_PLAY > _IDLE_SECS:
time.sleep(60) # nobody's watching: don't burn upstream bandwidth
continue
try:
m = upstream.master_m3u8(1, "jpn")
if not m:
@@ -97,7 +108,7 @@ def _cdn_probe():
_CDN["hist"].append({"t": time.time(), "kbps": round(kbps)})
del _CDN["hist"][:-20]
_origin_probe()
time.sleep(180)
time.sleep(_DEGRADED_RETRY if now == "DEGRADED" else 180)
def _origin_probe():
@@ -559,6 +570,8 @@ def api_episodes(anime_id: int):
@app.get("/api/episode/{ep_id}/stream")
def api_stream(ep_id: int, lang: str = "jpn", request: Request = None):
global _LAST_PLAY
_LAST_PLAY = time.time() # wakes the CDN probe: a viewer is here
def go():
master = _upstream(upstream.master_m3u8, ep_id, lang)
if not master: