Provider-Interface (nominatim|none), strukturierte Suche mit User-Agent und Accept-Language, Drosselung 1/s je Prozess, Job geocode-site (Worker: Concurrency 1 + Limiter), Cache am Objekt, manuelle Koordinaten bleiben, Auslöser Anlage/Adressänderung/Import-Bestätigung nur per Queue, Backfill-Skript, Env-Beispiele. Tests mit Fake-Provider, Nominatim nie aufgerufen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
25 lines
972 B
TypeScript
25 lines
972 B
TypeScript
/**
|
|
* Minimum-interval limiter: callers are released one after another with at least `intervalMs`
|
|
* between two slots (Nominatim policy: max. 1 request per second). Clock is injectable for tests.
|
|
*/
|
|
export type Clock = { now: () => number; sleep: (ms: number) => Promise<void> };
|
|
|
|
const realClock: Clock = { now: () => Date.now(), sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)) };
|
|
|
|
export function createIntervalLimiter(intervalMs: number, clock: Clock = realClock) {
|
|
let next = 0;
|
|
return {
|
|
/** Waits for the next free slot and returns its timestamp. */
|
|
async acquire(): Promise<number> {
|
|
const now = clock.now();
|
|
const slot = Math.max(now, next);
|
|
next = slot + intervalMs;
|
|
if (slot > now) await clock.sleep(slot - now);
|
|
return slot;
|
|
},
|
|
};
|
|
}
|
|
|
|
/** Process-wide limiter for all Nominatim requests of this process (worker, backfill script). */
|
|
export const nominatimLimiter = createIntervalLimiter(1_000);
|