| |
export function cached<Args extends unknown[], V>(
|
| |
f: (...args: Args) => Promise<V>,
|
| |
makeKey: (...args: Args) => string,
|
| - |
options?: LRUCache.Options<string, { value: V }, unknown>,
|
| + |
options?: LRUCache.Options<string, { promise: Promise<V> }, unknown>,
|
| |
): (...args: Args) => Promise<V> {
|
| |
const cache = new LRUCache(options || { max: 500 });
|
| - |
return async function (...args: Args): Promise<V> {
|
| + |
return function (...args: Args): Promise<V> {
|
| |
const key = makeKey(...args);
|
| - |
const cached = cache.get(key);
|
| + |
const hit = cache.get(key);
|
| + |
if (hit !== undefined) return hit.promise;
|
| |
|
| - |
if (cached === undefined) {
|
| - |
const value = await f(...args);
|
| - |
cache.set(key, { value });
|
| - |
return value;
|
| - |
} else {
|
| - |
return cached.value;
|
| - |
}
|
| + |
const promise = f(...args);
|
| + |
// Evict on rejection so the next caller can retry with a fresh request.
|
| + |
promise.catch(() => {
|
| + |
cache.delete(key);
|
| + |
});
|
| + |
cache.set(key, { promise });
|
| + |
return promise;
|
| |
};
|
| |
}
|