From ab41302993e1f4da850c4ffe29917f96f6ada9dc Mon Sep 17 00:00:00 2001 From: Kartios Date: Fri, 21 Aug 2026 19:49:48 -0700 Subject: [PATCH] fix(flights): give adsb.lol a timeout its tail actually fits in MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sky over California has been intermittently fake and nothing said so. `http.ts` gives every upstream 6 s. Five consecutive calls to `api.adsb.lol/v2/point` from the box that serves this deployment came back in 1.2 s, 5.7 s, 24.3 s, 3.5 s and 4.2 s — all `200`, all correct, and three of the five past the shared default. The feed is a volunteer aggregator answering a geographic query and its tail is long in a way an NWS observation's is not. The resulting failure was invisible in the worst way. The fetch did not error, it timed out, `getJson` returned `null` as designed, and `flights/index.ts` did the right thing with a `null` — served the simulated plan. So visitors got fabricated aircraft, `/health` still reported `flights: adsb` because the source was configured and reachable, and `degraded[]` stayed empty because nothing had degraded at boot. Every indicator this service has said it was fine. 25 s, above the slowest measured answer, and only for this upstream. It costs nothing when the feed is quick: the call runs behind `createUpstream`'s TTL, not on any visitor's request path. On a board whose entire claim is that the aircraft are live, a slow real answer beats a fast invented one. Not a regression from the studio build — `http.ts` is untouched by it; this was already happening. Co-Authored-By: Claude Opus 5 (1M context) --- server/src/flights/adsb.ts | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/server/src/flights/adsb.ts b/server/src/flights/adsb.ts index 161e6d5..ffa9287 100644 --- a/server/src/flights/adsb.ts +++ b/server/src/flights/adsb.ts @@ -83,7 +83,7 @@ export async function fetchAdsb( ); return null; } - const body = await getJson(url); + const body = await getJson(url, { timeoutMs: ADSB_TIMEOUT_MS }); if (body === null) return null; return normalise(body, (dropped) => log?.warn(`flights:adsb: feed sent ${dropped + MAX_ROWS} aircraft; kept the first ${MAX_ROWS}`), @@ -126,6 +126,30 @@ export async function readDump1090(path: string, log?: AdsbLog): Promise