mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-11 05:42:22 +00:00
fix(shipwrecks): a source refresh with less than half of its last good wrecks is refused until the old set expires
A 200 answer that was valid but cut short (30 Wikidata wrecks instead of about 1,450) replaced the last good set for a day. It now counts as a failed refresh: the old records are served as stale and the source is retried after 15 minutes; once the old set is past seven days, the new one is taken.
This commit is contained in:
1 parent
0c159186f9
commit
66fba3da47
2 files changed
+45
-1
No files matched your search
@@ -15,6 +15,8 @@ const REFRESH_MS = 24 * 60 * 60 * 1000;
|
||||
const STALE_MAX_MS = 7 * REFRESH_MS;
|
||||
/** After a source fails, it is not asked again for this long. */
|
||||
const RETRY_MS = 15 * 60 * 1000;
|
||||
/** A refresh with fewer than this share of the last good records is refused. */
|
||||
const MIN_KEEP_RATIO = 0.5;
|
||||
// Only the columns the card uses; ship_char/obj_desc histories can name people
|
||||
// and are not read beyond a short vessel type.
|
||||
const EMODNET_PROPERTIES = [
|
||||
@@ -109,7 +111,13 @@ export function shipwrecksProxy({
|
||||
const done = now();
|
||||
results.forEach((result, i) => {
|
||||
const state = sources[names[i]];
|
||||
if (result.status === 'fulfilled')
|
||||
// A valid answer far smaller than the last good set (a truncated or
|
||||
// half-built upstream) is a failure too, until the old set expires.
|
||||
const shrunk =
|
||||
result.status === 'fulfilled' &&
|
||||
usable(state, done) &&
|
||||
result.value.length < state.good.records.length * MIN_KEEP_RATIO;
|
||||
if (result.status === 'fulfilled' && !shrunk)
|
||||
state.good = { records: result.value, fetchedAt: done };
|
||||
else state.retryAt = done + RETRY_MS;
|
||||
});
|
||||
|
||||
@@ -292,3 +292,39 @@ test('an upstream body over its cap is a failed source, read only to the cap', a
|
||||
assert.ok(cancelled, 'the oversized body is cancelled');
|
||||
assert.ok(sent <= 34 * MIB, `read ${sent / MIB} MiB of a 32 MiB cap`);
|
||||
});
|
||||
|
||||
test('a refresh far smaller than the last good set is refused until it expires', async () => {
|
||||
let clock = 0;
|
||||
const many = {
|
||||
results: {
|
||||
bindings: Array.from({ length: 10 }, (_, i) => ({
|
||||
item: { value: `http://www.wikidata.org/entity/Q${100 + i}` },
|
||||
itemLabel: { value: `Wreck ${i}` },
|
||||
coord: { value: `Point(${i} 40)` },
|
||||
})),
|
||||
},
|
||||
};
|
||||
let wikidata = many;
|
||||
const handler = handlerOf(
|
||||
shipwrecksProxy({
|
||||
fetchImpl: async (url) =>
|
||||
Response.json(
|
||||
String(url).includes('query.wikidata.org') ? wikidata : EMODNET,
|
||||
),
|
||||
now: () => clock,
|
||||
}),
|
||||
);
|
||||
assert.equal((await request(handler)).body.records.length, 11);
|
||||
wikidata = WIKIDATA;
|
||||
clock = 25 * HOUR;
|
||||
const refused = await request(handler);
|
||||
assert.equal(refused.body.records.length, 11, 'one wreck is not ten');
|
||||
assert.equal(refused.body.stale, true);
|
||||
clock = 8 * 24 * HOUR;
|
||||
const accepted = await request(handler);
|
||||
assert.equal(
|
||||
accepted.body.records.length,
|
||||
2,
|
||||
'taken once the old set expired',
|
||||
);
|
||||
});
|
||||
Reference in new issue
Block a user