mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 02:14:01 +00:00
fix(overpass): tag caches by the sorted upstream set and cover installations
Uses a full SHA-256 of the sorted instance list, so reordering the same instances for failover keeps the cache. Adds the installation-cache repoint test (tagged, reordered, repointed, untagged, unconfigured) and the changelog and current-state notes.
This commit is contained in:
1 parent
4ede4ebbcd
commit
c42b072e99
4 files changed
+39
-4
No files matched your search
@@ -1,5 +1,8 @@
|
||||
# Changelog
|
||||
|
||||
- Overpass and military-installation disk caches no longer serve answers from a
|
||||
previously configured `OVERPASS_UPSTREAMS` instance after it is repointed.
|
||||
|
||||
- A Radio Browser mirror answering 204, 205 or 304, or a status outside
|
||||
200–599, no longer crashes the local dev/preview server. Null-body statuses
|
||||
get an empty body; anything else that cannot become a response fails that
|
||||
|
||||
@@ -4132,6 +4132,10 @@ for, resolved lazily after env loading. It replaces the empty default list;
|
||||
there is no built-in fallback. Local/private instances are allowed. The stable
|
||||
`gods-eye-view/…` User-Agent is unchanged. URLs never appear in response headers
|
||||
or upstream errors, including old cached endpoint metadata.
|
||||
Disk cache entries for both routes carry a SHA-256 tag of the configured
|
||||
instance set (order does not matter) and are served only while it matches, so
|
||||
repointing `OVERPASS_UPSTREAMS` refetches instead of serving another instance's
|
||||
answers; untagged entries stop serving once an instance is configured.
|
||||
|
||||
The shared transport guards `/api/overpass` and `/api/military-installations`.
|
||||
With no configured upstream, each route serves existing cache data (including
|
||||
|
||||
@@ -40,10 +40,10 @@ let upstreamMemo = { raw: null, endpoints: [], tag: 'none' };
|
||||
*/
|
||||
function upstreamTag(endpoints) {
|
||||
if (!endpoints.length) return 'none';
|
||||
return createHash('sha1')
|
||||
.update(endpoints.join('\n'))
|
||||
.digest('hex')
|
||||
.slice(0, 12);
|
||||
// Sorted, so reordering the same instances for failover keeps the cache.
|
||||
return createHash('sha256')
|
||||
.update([...endpoints].sort().join('\n'))
|
||||
.digest('hex');
|
||||
}
|
||||
|
||||
/** Resolve after environment loading. Public Overpass instances are not used by default. */
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
validMilitaryInstallationBox,
|
||||
writeMilitaryInstallationDisk,
|
||||
} from '../../vite.config.js';
|
||||
import { resolveOverpassUpstreamTag } from '../../server/providers/overpass/constants.js';
|
||||
|
||||
const DAY_MS = 86_400_000;
|
||||
test('installation failure reasons disclose no raw upstream error and do not guess overload', () => {
|
||||
@@ -274,3 +275,30 @@ test('an unwritable cache directory degrades to a miss instead of throwing', asy
|
||||
await fsp.rm(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test('an installation entry is not served after OVERPASS_UPSTREAMS is repointed', async (t) => {
|
||||
const prior = process.env.OVERPASS_UPSTREAMS;
|
||||
t.after(() => {
|
||||
if (prior === undefined) delete process.env.OVERPASS_UPSTREAMS;
|
||||
else process.env.OVERPASS_UPSTREAMS = prior;
|
||||
});
|
||||
const dir = tempCacheDir();
|
||||
const key = '30.250,-97.750,30.300,-97.700';
|
||||
try {
|
||||
process.env.OVERPASS_UPSTREAMS = 'https://a.example/api/interpreter,https://b.example/api/interpreter';
|
||||
const tag = resolveOverpassUpstreamTag();
|
||||
await writeMilitaryInstallationDisk(key, { ...entry(Date.now()), upstreams: tag }, dir);
|
||||
assert.ok(await readMilitaryInstallationDisk(key, TTL_MS, dir), 'its own entry is a hit');
|
||||
process.env.OVERPASS_UPSTREAMS = 'https://b.example/api/interpreter,https://a.example/api/interpreter';
|
||||
assert.equal(resolveOverpassUpstreamTag(), tag, 'reordering the same instances keeps the tag');
|
||||
process.env.OVERPASS_UPSTREAMS = 'https://c.example/api/interpreter';
|
||||
assert.equal(await readMilitaryInstallationDisk(key, TTL_MS, dir), null, 'fresh read refused');
|
||||
assert.equal(await readMilitaryInstallationDisk(key, Infinity, dir), null, 'stale read refused');
|
||||
await writeMilitaryInstallationDisk('legacy', entry(Date.now()), dir);
|
||||
assert.equal(await readMilitaryInstallationDisk('legacy', Infinity, dir), null, 'untagged entry refused');
|
||||
delete process.env.OVERPASS_UPSTREAMS;
|
||||
assert.ok(await readMilitaryInstallationDisk(key, Infinity, dir), 'nothing configured accepts any entry');
|
||||
} finally {
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user