fix(satellites): a SATCAT failure no longer stops TLE refreshes

Both CelesTrak routes shared one cooldown, and any failure set it: one bad
SATCAT answer made /api/celestrak return 502 "cooling down" for a minute,
failing the Starlink load and stalling every TLE group past its cache.
Throttling (403/429) still holds both routes off, since CelesTrak throttles
the client; any other failure holds off only the route that failed.
This commit is contained in:
Sameh Khamis committed 2026-11-08 15:16:01 -08:00
1 parent d404445da3
commit 8ae56587c3
2 files changed
+53 -12

No files matched your search

+34
View File
@@ -359,6 +359,40 @@ test('SATCAT is proxied per core group for a day, separately from TLEs, and serv
assert.equal(stale.headers['x-satcat-cache'], 'STALE-ERROR');
});
test('a SATCAT failure never holds off the TLEs, but CelesTrak throttling holds off both', async (t) => {
isolateDisk(t);
t.mock.method(console, 'warn', () => {});
const tle =
'ISS (ZARYA)\n1 25544U 98067A 24001.00000000 .00016717 00000-0 10270-3 0 9001\n2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.50000000 04\n';
let satcatAnswer = () => new Response('<html>not csv</html>');
const fetched = [];
t.mock.method(globalThis, 'fetch', async (url) => {
const parsed = new URL(url);
fetched.push(parsed.pathname);
return parsed.pathname.startsWith('/satcat/')
? satcatAnswer()
: new Response(tle);
});
const request = install(celestrakProxy());
assert.equal((await request('/api/celestrak-satcat', '/sar')).status, 502);
const starlink = await request('/api/celestrak', '/starlink');
assert.equal(starlink.status, 200, 'the TLE feed is not cooling down');
assert.equal(starlink.body, tle);
// A 429 is CelesTrak throttling this client: every feed waits it out.
satcatAnswer = () =>
new Response('slow down', {
status: 429,
headers: { 'Retry-After': '120' },
});
const throttled = install(celestrakProxy());
await throttled('/api/celestrak-satcat', '/visual');
const before = fetched.length;
const held = await throttled('/api/celestrak', '/geo');
assert.equal(held.status, 502);
assert.equal(fetched.length, before, 'nothing went upstream');
});
test('CelesTrak admits a same-origin request behind the documented reverse proxy and refuses foreign origins', async (t) => {
isolateDisk(t);
let calls = 0;