v0.5.110: stop carrying stale live badges; probe live status in local serve.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+63
-3
@@ -19,7 +19,9 @@ import argparse
|
||||
import json
|
||||
import mimetypes
|
||||
import threading
|
||||
import time
|
||||
import webbrowser
|
||||
from datetime import datetime, timezone
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
from urllib.parse import urlparse
|
||||
|
||||
@@ -47,11 +49,15 @@ from shared.paths import (
|
||||
)
|
||||
from shared.relations import DEFAULT_RELATIONS, load_relations
|
||||
|
||||
from fetch_streamer_live import probe_streamers
|
||||
from mechanic_tags import QUERY_MECHANIC_ORDER, mechanic_query_payload
|
||||
|
||||
WEB_DIR = WEB_FRONTEND
|
||||
MOBILE_DEMAND_PATH = ROOT / "web" / ".refresh" / "mobile_demand.json"
|
||||
_MOBILE_DEMAND_LOCK = threading.Lock()
|
||||
_LIVE_STATUS_LOCK = threading.Lock()
|
||||
_LIVE_STATUS_TTL = 60
|
||||
_LIVE_STATUS_CACHE: tuple[float, dict] | None = None
|
||||
|
||||
|
||||
def _read_mobile_demand_count() -> int:
|
||||
@@ -76,6 +82,62 @@ def _inc_mobile_demand_count() -> int:
|
||||
return n
|
||||
|
||||
|
||||
def _probe_live_status() -> dict:
|
||||
"""Probe local streamer rooms without mutating streamers.json."""
|
||||
global _LIVE_STATUS_CACHE
|
||||
now = time.monotonic()
|
||||
cached = _LIVE_STATUS_CACHE
|
||||
if cached and now - cached[0] < _LIVE_STATUS_TTL:
|
||||
return cached[1]
|
||||
|
||||
with _LIVE_STATUS_LOCK:
|
||||
now = time.monotonic()
|
||||
cached = _LIVE_STATUS_CACHE
|
||||
if cached and now - cached[0] < _LIVE_STATUS_TTL:
|
||||
return cached[1]
|
||||
|
||||
try:
|
||||
payload = json.loads(STREAMERS_PATH.read_text(encoding="utf-8"))
|
||||
except (OSError, json.JSONDecodeError):
|
||||
result = {
|
||||
"probed_at": datetime.now(timezone.utc).isoformat(),
|
||||
"ttl": _LIVE_STATUS_TTL,
|
||||
"streamers": {},
|
||||
}
|
||||
_LIVE_STATUS_CACHE = (now, result)
|
||||
return result
|
||||
|
||||
rows = payload.get("streamers")
|
||||
if not isinstance(rows, list):
|
||||
rows = []
|
||||
for row in rows:
|
||||
if isinstance(row, dict) and row.get("live_url"):
|
||||
# A failed probe is unknown and must not preserve a stale live badge.
|
||||
row["is_live"] = False
|
||||
row.pop("live_probed_at", None)
|
||||
|
||||
probe_streamers(payload)
|
||||
streamers = {}
|
||||
for row in rows:
|
||||
if not isinstance(row, dict) or not row.get("live_url"):
|
||||
continue
|
||||
sid = str(row.get("id") or "").strip()
|
||||
if not sid:
|
||||
continue
|
||||
cell = {"is_live": row.get("is_live") is True}
|
||||
if not row.get("live_probed_at"):
|
||||
cell["stale"] = True
|
||||
streamers[sid] = cell
|
||||
|
||||
result = {
|
||||
"probed_at": datetime.now(timezone.utc).isoformat(),
|
||||
"ttl": _LIVE_STATUS_TTL,
|
||||
"streamers": streamers,
|
||||
}
|
||||
_LIVE_STATUS_CACHE = (time.monotonic(), result)
|
||||
return result
|
||||
|
||||
|
||||
GRID_ORDER_PATH = DATA / "hero_grid_order.json"
|
||||
HERO_ITEMS_PATH = DATA / "hero_items.json"
|
||||
HERO_STATS_PATH = DATA / "hero_stats.json"
|
||||
@@ -842,9 +904,7 @@ class Handler(BaseHTTPRequestHandler):
|
||||
self._json(200, build_payload())
|
||||
return
|
||||
if path == "/api/live-status":
|
||||
# Local-dev stub for the Pages Function (edge probing runs in
|
||||
# production only); the empty map keeps the UI on data.json is_live.
|
||||
self._json(200, {"probed_at": None, "ttl": 300, "streamers": {}})
|
||||
self._json(200, _probe_live_status())
|
||||
return
|
||||
if path == "/api/mobile-demand":
|
||||
self._json(200, {"count": _read_mobile_demand_count()})
|
||||
|
||||
Reference in New Issue
Block a user