mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
328b5fcb2b
Atlas throttled to the 1.1s OSM asks for and cached its answers in a 50k map; maps did neither, so five interactive routes fired straight at the service while the two atlas backfill loops politely waited their turn. From Nominatim's side that is one instance ignoring the rate limit. Both go through geo/nominatim.client.ts now. Three things the naive merge would have got wrong: - The shared client sends UA, the instance-identifying User-Agent, not the generic string atlas used. A shared generic UA is throttled harder. - One cursor across five interactive routes and two background loops would have put a keystroke behind however many places the backfill enqueued, so there are two lanes over the one cursor and background yields. - The cache key carries the query shape. Atlas asks at zoom 3 and 8, maps at 18; a coordinate-only key answers a street lookup with a country. The throttle cursor and the cache stay module state, the way the permissions and FX caches do, because the bridges build their collaborators outside the container and a second copy of the cursor is the bug being removed here. GeocodingService owns only the cleanup timer's lifecycle, which atlas used to start as an import-time side effect. Also folds the three haversine implementations into common/geo.ts, keeping the clamped form: asin of a value a hair over 1 is NaN, and a NaN distance fails every comparison it feeds instead of throwing. tests/setup.ts zeroes the interval. Nineteen maps cases drive these paths back to back with real timers and were sleeping nineteen seconds for it.
38 lines
2.2 KiB
TypeScript
38 lines
2.2 KiB
TypeScript
// Global test setup — runs before every test file.
|
|
// Environment variables must be set before any module import so that
|
|
// config.ts, database.ts, etc. pick them up at import time. (Importing from
|
|
// 'vitest' itself is safe: it is externalized and pulls in no app modules.)
|
|
import { afterEach } from 'vitest';
|
|
|
|
// Fixed encryption key (64 hex chars = 32 bytes) for at-rest crypto in tests
|
|
process.env.ENCRYPTION_KEY = 'a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2a3b4c5d6a7b8c9d0e1f2';
|
|
process.env.NODE_ENV = 'test';
|
|
process.env.COOKIE_SECURE = 'false';
|
|
process.env.LOG_LEVEL = 'error'; // suppress info/debug logs in test output
|
|
|
|
// Several services fire notification sends as unawaited dynamic-import chains
|
|
// (`import('…/notificationService').then(({ send }) => send(…).catch(…))`).
|
|
// Give those chains one macrotask turn to settle after every test, while the
|
|
// suite's DB and the worker environment are still alive — otherwise the last
|
|
// test in a file can leave the chain pending into worker teardown ("Cannot
|
|
// load ... after the environment was torn down"). Under the default "stack"
|
|
// hook order this afterEach runs after each test's own afterEach and before
|
|
// the suite's afterAll, i.e. before any afterAll closes its test DB.
|
|
// setImmediate is captured up front because some suites install fake timers.
|
|
const realSetImmediate = globalThis.setImmediate;
|
|
afterEach(async () => {
|
|
await new Promise((resolve) => realSetImmediate(resolve));
|
|
});
|
|
|
|
// Nominatim's rate limit is a property of the real service, not of the code
|
|
// under test. Nineteen maps cases stub fetch and drive those paths back to back;
|
|
// under the real 1.1s interval they would spend nineteen seconds asleep. The
|
|
// cases that are actually about the throttle set it back for themselves.
|
|
//
|
|
// Imported dynamically, and down here rather than at the top: the client pulls
|
|
// in maps.helpers, whose UA constant calls getAppUrl() at module load. A static
|
|
// import is hoisted above the assignments above it, so the URL would be read
|
|
// from an environment this file has not finished setting up yet.
|
|
const { setGeoThrottleInterval } = await import('../src/nest/geo/nominatim.client');
|
|
setGeoThrottleInterval(0);
|