Background CDN probe: log throughput + state flips every 3 min
64KB Range fetch from a fixed episode (JJK S2 E25) on a daemon thread; logs '[probe] CDN OK/DEGRADED (N KB/s)' on state change so server.log shows exactly when a degraded window ends. 18/18 tests, verified live.
This commit is contained in:
1 parent
4c5dbab4b0
commit
eea538ab17
1 file changed
+37
@@ -7,6 +7,7 @@ Cloudflare workaround) and rewrites playlist URIs to go through itself.
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
from collections import Counter, OrderedDict
|
||||
from datetime import datetime
|
||||
@@ -24,6 +25,42 @@ from . import db, upstream, users
|
||||
ROOT = Path(__file__).parent.parent
|
||||
app = FastAPI(title="ani-web")
|
||||
|
||||
|
||||
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).
|
||||
Probe target: any valid episode (36019 = JJK S2 E25).
|
||||
ponytail: single fixed episode; if it ever disappears, the probe logs
|
||||
DEGRADED forever — swap the ID, don't build a picker."""
|
||||
def first(pl, base):
|
||||
l = next(x.strip() for x in pl.splitlines()
|
||||
if x.strip() and not x.startswith("#"))
|
||||
return l if l.startswith("http") else base + l
|
||||
|
||||
state = None
|
||||
while True:
|
||||
try:
|
||||
m = upstream.master_m3u8(36019, "jpn")
|
||||
if not m:
|
||||
raise RuntimeError("no master m3u8")
|
||||
base = m.rsplit("/", 1)[0] + "/"
|
||||
v = first(upstream._get(m, timeout=10).text, base)
|
||||
seg = first(upstream._get(v, timeout=10).text, base)
|
||||
t = time.time()
|
||||
r = upstream._session().get(seg, headers={"Range": "bytes=0-65535"},
|
||||
impersonate="chrome", timeout=10)
|
||||
kbps = len(r.content) / 1024 / max(time.time() - t, 0.01)
|
||||
except Exception:
|
||||
kbps = 0.0
|
||||
now = "OK" if kbps >= 40 else "DEGRADED"
|
||||
if now != state:
|
||||
print(f"[probe] CDN {now} ({kbps:.0f} KB/s)", flush=True)
|
||||
state = now
|
||||
time.sleep(180)
|
||||
|
||||
|
||||
threading.Thread(target=_cdn_probe, daemon=True).start()
|
||||
|
||||
# ---------- auth: multi-user, signed cookies ----------
|
||||
users.migrate_legacy() # file-based legacy import; db.init() absorbs its output
|
||||
db.init()
|
||||
|
||||
Reference in new issue
Block a user