Did you clear cache before opening an issue?
Is there an existing issue for this?
Does the issue happen when logged in?
N/A
Does the issue happen when logged out?
N/A (backend source bug)
Does the issue happen in incognito mode when logged in?
N/A
Does the issue happen in incognito mode when logged out?
N/A
Issue details
Current Behavior
cacheWithTTL in backend/src/utils/ttl-cache.ts marks the cache as fresh before the fetch resolves:
// backend/src/utils/ttl-cache.ts:20-26
return async () => {
if (lastFetchTime < Date.now() - ttlMs) {
lastFetchTime = Date.now(); // updated before await completes
cache = await fn();
}
return cache;
};
Consequences:
- Failed fetch poisons the cache for the full TTL. If
fn() rejects, the rejection propagates to that caller, but lastFetchTime has already been advanced — every subsequent call within the TTL returns stale cached data instead of retrying. This utility backs the PSA endpoint (controllers/psa.ts), so one failed upstream fetch serves stale content for the whole TTL window.
- No in-flight promise dedup. When the TTL expires under concurrent requests, all callers run
fn() simultaneously (thundering herd) since nothing records the pending promise.
Expected Behavior
Only advance lastFetchTime after a successful fetch, and dedupe concurrent calls by caching the promise itself:
let lastFetchTime = 0;
let cache: T | undefined;
let inflight: Promise<T> | undefined;
return async () => {
if (lastFetchTime < Date.now() - ttlMs) {
inflight ??= fn()
.then((result) => {
cache = result;
lastFetchTime = Date.now();
return result;
})
.finally(() => {
inflight = undefined;
});
return inflight;
}
return cache;
};
Steps To Reproduce
- Call a
cacheWithTTL-wrapped getter whose fn throws.
- Call again within the TTL — stale data is returned with no retry until TTL expiry.
Environment
Did you clear cache before opening an issue?
Is there an existing issue for this?
Does the issue happen when logged in?
N/A
Does the issue happen when logged out?
N/A (backend source bug)
Does the issue happen in incognito mode when logged in?
N/A
Does the issue happen in incognito mode when logged out?
N/A
Issue details
Current Behavior
cacheWithTTLinbackend/src/utils/ttl-cache.tsmarks the cache as fresh before the fetch resolves:Consequences:
fn()rejects, the rejection propagates to that caller, butlastFetchTimehas already been advanced — every subsequent call within the TTL returns stale cached data instead of retrying. This utility backs the PSA endpoint (controllers/psa.ts), so one failed upstream fetch serves stale content for the whole TTL window.fn()simultaneously (thundering herd) since nothing records the pending promise.Expected Behavior
Only advance
lastFetchTimeafter a successful fetch, and dedupe concurrent calls by caching the promise itself:Steps To Reproduce
cacheWithTTL-wrapped getter whosefnthrows.Environment
master@ 91bd24b