File size: 918 Bytes
1a8147e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | type CacheEntry<T> = {
expiresAt: number;
value: Promise<T>;
};
export class TtlCache<T = unknown> {
private readonly store = new Map<string, CacheEntry<T>>();
async getOrSet(
key: string,
ttlMs: number,
loader: () => Promise<T>,
): Promise<T> {
const now = Date.now();
const cached = this.store.get(key);
if (cached && cached.expiresAt > now) {
return cached.value;
}
const value = loader().catch((error) => {
const current = this.store.get(key);
if (current?.value === value) {
this.store.delete(key);
}
throw error;
});
this.store.set(key, {
expiresAt: now + ttlMs,
value,
});
return value;
}
clear() {
this.store.clear();
}
deletePrefix(prefix: string) {
for (const key of this.store.keys()) {
if (key.startsWith(prefix)) {
this.store.delete(key);
}
}
}
}
|