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:
1 parent
0cd79dd701
commit
1154203569
1 file changed
+17
-4
+17
-4
@@ -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:
|
||||
|
||||
Reference in new issue
Block a user