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 base64
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import threading
|
||||||
import time
|
import time
|
||||||
from collections import Counter, OrderedDict
|
from collections import Counter, OrderedDict
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -24,6 +25,42 @@ from . import db, upstream, users
|
|||||||
ROOT = Path(__file__).parent.parent
|
ROOT = Path(__file__).parent.parent
|
||||||
app = FastAPI(title="ani-web")
|
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 ----------
|
# ---------- auth: multi-user, signed cookies ----------
|
||||||
users.migrate_legacy() # file-based legacy import; db.init() absorbs its output
|
users.migrate_legacy() # file-based legacy import; db.init() absorbs its output
|
||||||
db.init()
|
db.init()
|
||||||
|
|||||||
Reference in new issue
Block a user