LRU-Speicher mit Ablaufzeit (lru.js), Cache-Instanz der öffentlichen Antwort (cache.js: 500 Einträge, 30 s) und Appwrite-Speicher mit getrennten Versionen für Kundendaten und Team-Einstellungen (speicher.js), alle Schreibzugriffe unter der Sperre zeiten:<projectId>. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
57 lines
2.2 KiB
JavaScript
57 lines
2.2 KiB
JavaScript
/**
|
|
* Oeffnungszeiten live: kleiner LRU-Speicher mit Ablaufzeit (rein, ohne eigene Uhr: die Zeit kommt als Millisekunden-Parameter).
|
|
*
|
|
* - hoechstens max Eintraege; ist er voll, faellt der am laengsten nicht benutzte (hole oder setze) heraus;
|
|
* - jeder Eintrag verfaellt ttlMs nach dem Setzen (genau nach ttlMs ist er weg); ein Treffer erneuert nur seinen Platz in
|
|
* der Reihe, nie die Ablaufzeit, damit auch ein oft abgefragter Eintrag spaetestens nach ttlMs neu gebaut wird;
|
|
* - hole liefert bei Fehlschlag oder Ablauf undefined; gespeichert werden darf jeder Wert (auch null, 0, '').
|
|
* Umsetzung: eine Map; ihre Einfuegereihenfolge ist die Nutzungsreihenfolge (aeltester zuerst), ein Treffer haengt den Eintrag neu an.
|
|
*/
|
|
|
|
const pruefeZeit = (nowMs, wer) => {
|
|
if (typeof nowMs !== 'number' || !Number.isFinite(nowMs)) throw new TypeError(`${wer}: nowMs muss eine Zahl (Millisekunden) sein`)
|
|
}
|
|
|
|
/**
|
|
* @param {{ max: number, ttlMs: number }} optionen max = ganze Zahl >= 1, ttlMs = Zahl > 0 (endlich)
|
|
* @returns {{ hole(key: string, nowMs: number): *, setze(key: string, wert: *, nowMs: number): void, vergiss(key: string): void, leere(): void, groesse(): number }}
|
|
*/
|
|
export function neuerLru({ max, ttlMs } = {}) {
|
|
if (!Number.isInteger(max) || max < 1) throw new TypeError('neuerLru: max muss eine ganze Zahl ab 1 sein')
|
|
if (typeof ttlMs !== 'number' || !Number.isFinite(ttlMs) || ttlMs <= 0) throw new TypeError('neuerLru: ttlMs muss eine Zahl groesser 0 sein')
|
|
|
|
/** @type {Map<string, { bis: number, wert: * }>} */
|
|
const eintraege = new Map()
|
|
|
|
return {
|
|
hole(key, nowMs) {
|
|
pruefeZeit(nowMs, 'hole')
|
|
const eintrag = eintraege.get(key)
|
|
if (!eintrag) return undefined
|
|
eintraege.delete(key)
|
|
if (eintrag.bis <= nowMs) return undefined
|
|
eintraege.set(key, eintrag)
|
|
return eintrag.wert
|
|
},
|
|
|
|
setze(key, wert, nowMs) {
|
|
pruefeZeit(nowMs, 'setze')
|
|
eintraege.delete(key)
|
|
eintraege.set(key, { bis: nowMs + ttlMs, wert })
|
|
while (eintraege.size > max) eintraege.delete(eintraege.keys().next().value)
|
|
},
|
|
|
|
vergiss(key) {
|
|
eintraege.delete(key)
|
|
},
|
|
|
|
leere() {
|
|
eintraege.clear()
|
|
},
|
|
|
|
groesse() {
|
|
return eintraege.size
|
|
},
|
|
}
|
|
}
|