dashboard: cut page sync latency to ~scan-time + ≤5 s

Three display-side fixes, no signal-logic changes:
- run_cycle publishes snapshot.json BEFORE the news refresh — news I/O
  (FF + 4 RSS + possible DeepSeek calls) took 20-30 s on TTL-expired
  cycles and kept fresh signals off the page (publish_all split into
  publish_snapshot/publish_news, kept for boot)
- page polls every 5 s (was 20 s) using conditional GETs: dropped the
  ?t= cache-buster + no-store so Apache answers unchanged files with
  bodyless 304s
- boundary refetch sniper re-armed: fires 2 s after next_scan_epoch
  regardless of distance (the old delay<POLL_MS guard would have been
  dead code at 5 s polling)

New Module 20 test locks the snapshot-before-news ordering. 352 tests.

Claude-Session: https://claude.ai/code/session_017mbXs9HRawZhD1uZ3ze7zQ
This commit is contained in:
Harwinder Sekhon
2026-08-06 22:35:13 -04:00
parent 858c12280a
commit a2f951f5c9
3 changed files with 43 additions and 10 deletions
+15
View File
@@ -5469,6 +5469,21 @@ def _():
assert os.listdir(tmp) == ["snapshot.json"] # no .tmp left
@test("dashboard: run_cycle publishes snapshot BEFORE news refresh")
def _():
# News I/O (FF + RSS + DeepSeek) can take 20-30 s — fresh signals
# must reach the page first (2026-08-06 sync-latency fix).
pub = dpub.DashboardPublisher(out_dir="/nonexistent")
order = []
pub.scan_tf = lambda tf: order.append(f"scan:{tf.value}")
pub.publish_snapshot = lambda: order.append("snapshot")
pub.refresh_news = lambda: order.append("news_refresh")
pub.publish_news = lambda: order.append("news_publish")
pub.run_cycle([Timeframe.M5])
assert order == ["scan:5min", "snapshot", "news_refresh",
"news_publish"], order
@test("dashboard: seconds_until_boundary bounds and constants")
def _():
for interval in (5, 15, 60, 240):