fix: prevent infinite loading screen by adding sweep timeouts

The dashboard would hang indefinitely on the loading screen because:

1. `bls.mjs` used a raw `fetch()` without any timeout/AbortSignal —
   if the BLS API was slow or unresponsive, it would block forever.

2. `runSource()` in `briefing.mjs` had no per-source timeout, so a
   single hanging API could stall the entire sweep indefinitely.

3. `server.mjs` loaded cached `latest.json` via a fire-and-forget
   promise (`.then()`) instead of `await`, meaning the dashboard
   never received the cached data before the sweep started.

4. `loading.html` relied solely on SSE for redirect — if the SSE
   connection missed the update event, the page would never redirect.

Changes:
- Add 15s AbortController timeout to BLS `getSeries()` fetch call
- Add 30s per-source timeout via `Promise.race()` in `runSource()`
- Await `synthesize()` when loading cached data so the dashboard
  serves instantly on restart when `runs/latest.json` exists
- Add 5s fallback polling to loading page alongside SSE

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Firdavs
2026-03-17 21:56:08 +03:00
parent 0200e6d9d5
commit d22f36e158
4 changed files with 48 additions and 18 deletions

View File

@@ -37,11 +37,15 @@ export async function getSeries(seriesIds, opts = {}) {
if (apiKey) payload.registrationkey = apiKey;
try {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 15000);
const res = await fetch(base, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
signal: controller.signal,
});
clearTimeout(timer);
return await res.json();
} catch (e) {
return { error: e.message };