40 lines
908 B
TypeScript
40 lines
908 B
TypeScript
export interface QueryCacheOptions {
|
|
ttlMs: number;
|
|
maxEntries: number;
|
|
now?: () => number;
|
|
}
|
|
|
|
export function createQueryCache(options: QueryCacheOptions) {
|
|
const now = options.now ?? Date.now;
|
|
const entries = new Map<string, { data: unknown; ts: number }>();
|
|
|
|
async function cached<T>(key: string, fn: () => Promise<T>): Promise<T> {
|
|
const hit = entries.get(key);
|
|
if (hit && now() - hit.ts < options.ttlMs) {
|
|
return hit.data as T;
|
|
}
|
|
|
|
const data = await fn();
|
|
entries.set(key, { data, ts: now() });
|
|
|
|
while (entries.size > options.maxEntries) {
|
|
const oldestKey = entries.keys().next().value;
|
|
if (oldestKey === undefined) break;
|
|
entries.delete(oldestKey);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
function clear() {
|
|
entries.clear();
|
|
}
|
|
|
|
return { cached, clear };
|
|
}
|
|
|
|
export const queryCache = createQueryCache({
|
|
ttlMs: 120_000,
|
|
maxEntries: 500,
|
|
});
|