mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
fix(status): preserve cached aircraft age and independent refresh errors
This commit is contained in:
1 parent
8eb6d09105
commit
dae5f45426
9 files changed
+174
-14
No files matched your search
@@ -258,10 +258,12 @@ test('military aircraft route serves stale cache on an upstream 429 and cools do
|
||||
assert.equal(limited.body, first.body);
|
||||
assert.equal(limited.headers['x-ads-b-cache'], 'STALE');
|
||||
assert.equal(limited.headers['x-ads-b-upstream-status'], '429');
|
||||
assert.equal(limited.headers['x-ads-b-cache-age-ms'], '13000');
|
||||
now += 5_000;
|
||||
const cooling = await request('/api/adsblol/mil');
|
||||
assert.equal(calls, 2, 'no upstream call inside the Retry-After window');
|
||||
assert.equal(cooling.headers['x-ads-b-cache'], 'STALE');
|
||||
assert.equal(cooling.headers['x-ads-b-cache-age-ms'], '18000');
|
||||
now += 16_000;
|
||||
await request('/api/adsblol/mil');
|
||||
assert.equal(calls, 3, 'upstream is retried once Retry-After elapses');
|
||||
@@ -277,6 +279,7 @@ test('military aircraft route relays an upstream 429 when nothing is cached', as
|
||||
const request = install(providers.adsbLolProxy());
|
||||
const limited = await request('/api/adsblol/mil');
|
||||
assert.equal(limited.statusCode, 429);
|
||||
assert.ok(limited.headers['retry-after']);
|
||||
const again = await request('/api/adsblol/mil');
|
||||
assert.equal(again.statusCode, 429);
|
||||
assert.equal(
|
||||
@@ -289,3 +292,64 @@ test('military aircraft route relays an upstream 429 when nothing is cached', as
|
||||
'a cooling-down miss carries Retry-After',
|
||||
);
|
||||
});
|
||||
|
||||
test('military fallback cancels a stalled 5xx body and starts cooldown at receipt', async (t) => {
|
||||
let now = 1_800_000_000_000;
|
||||
let calls = 0;
|
||||
let cancelled = false;
|
||||
t.mock.method(Date, 'now', () => now);
|
||||
t.mock.method(console, 'warn', () => {});
|
||||
t.mock.method(globalThis, 'fetch', async () => {
|
||||
if (++calls === 1) return Response.json({ ac: [] });
|
||||
now += 10000;
|
||||
return new Response(
|
||||
new ReadableStream({
|
||||
cancel() {
|
||||
cancelled = true;
|
||||
},
|
||||
}),
|
||||
{
|
||||
status: 503,
|
||||
headers: { 'Retry-After': new Date(now + 20000).toUTCString() },
|
||||
},
|
||||
);
|
||||
});
|
||||
const request = install(providers.adsbLolProxy());
|
||||
await request('/api/adsblol/mil');
|
||||
now += 1000;
|
||||
const hit = await request('/api/adsblol/mil');
|
||||
assert.equal(hit.headers['x-ads-b-cache-age-ms'], '1000');
|
||||
now += 12000;
|
||||
const fallback = await request('/api/adsblol/mil');
|
||||
assert.equal(fallback.statusCode, 200);
|
||||
assert.equal(cancelled, true);
|
||||
assert.equal(fallback.headers['x-ads-b-cache-age-ms'], '23000');
|
||||
assert.equal(fallback.headers['x-ads-b-retry-after-seconds'], '20');
|
||||
now += 19000;
|
||||
await request('/api/adsblol/mil');
|
||||
assert.equal(calls, 2);
|
||||
now += 2000;
|
||||
await request('/api/adsblol/mil');
|
||||
assert.equal(calls, 3);
|
||||
});
|
||||
|
||||
test('military cooldown bounds untrusted Retry-After and defaults server errors', async (t) => {
|
||||
t.mock.method(console, 'warn', () => {});
|
||||
for (const [status, raw, seconds] of [
|
||||
[429, '1', 5],
|
||||
[429, '99999', 120],
|
||||
[503, 'invalid', 15],
|
||||
]) {
|
||||
t.mock.method(
|
||||
globalThis,
|
||||
'fetch',
|
||||
async () =>
|
||||
new Response('{}', {
|
||||
status,
|
||||
headers: { 'Retry-After': raw },
|
||||
}),
|
||||
);
|
||||
const result = await install(providers.adsbLolProxy())('/api/adsblol/mil');
|
||||
assert.equal(Number(result.headers['retry-after']), seconds);
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user