/** * Prozesslokaler Cache mit Verfallszeit und Obergrenze. * * Die Rechteauflösung läuft einmal pro Request. Ohne Cache wären das zwei * Abfragen auf jeder Seite, mit Cache praktisch keine. Die Verfallszeit ist * nur das Sicherheitsnetz: der eigentliche Weg ist die sofortige Verwerfung * über `pg_notify`, siehe lib/realtime/listener.ts und docs/03-auth-und-rechte.md. */ export class TtlCache { readonly #entries = new Map() constructor( private readonly ttlMs: number, private readonly maxEntries: number, ) {} get(key: K): V | undefined { const entry = this.#entries.get(key) if (!entry) return undefined if (entry.expiresAt <= Date.now()) { this.#entries.delete(key) return undefined } // Auffrischen, damit die Reihenfolge der Map die Nutzung widerspiegelt. this.#entries.delete(key) this.#entries.set(key, entry) return entry.value } set(key: K, value: V): void { this.#entries.delete(key) this.#entries.set(key, { value, expiresAt: Date.now() + this.ttlMs }) while (this.#entries.size > this.maxEntries) { const oldest = this.#entries.keys().next() if (oldest.done) break this.#entries.delete(oldest.value) } } delete(key: K): void { this.#entries.delete(key) } clear(): void { this.#entries.clear() } get size(): number { return this.#entries.size } }