perf(cache): bound reported-failures set and halve default in-process budget
CI / check (push) Successful in 45s
CI / tests-integration (push) Successful in 2m22s
CI / tests-unit (push) Successful in 2m35s
CI / tests-quality (push) Successful in 1m5s
CI / tests-imaging-browsers (push) Successful in 1m57s
CI / tests-ui (push) Successful in 6m9s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 22s
CI / check (push) Successful in 45s
CI / tests-integration (push) Successful in 2m22s
CI / tests-unit (push) Successful in 2m35s
CI / tests-quality (push) Successful in 1m5s
CI / tests-imaging-browsers (push) Successful in 1m57s
CI / tests-ui (push) Successful in 6m9s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 22s
This commit is contained in:
1 parent
e4564abc5e
commit
e96c408ac1
1 file changed
+14
-3
+14
-3
@@ -49,7 +49,7 @@ function readPositiveInt(name: string, fallback: number): number {
|
|||||||
// In-process budget. Entries are evicted least-recently-*used* (see getMemory),
|
// In-process budget. Entries are evicted least-recently-*used* (see getMemory),
|
||||||
// so a hot key only leaves when a hotter one takes its place. The default is
|
// so a hot key only leaves when a hotter one takes its place. The default is
|
||||||
// generous because the layer exists to keep origin calls off the hot path.
|
// generous because the layer exists to keep origin calls off the hot path.
|
||||||
const MAX_MEMORY_ENTRIES = readPositiveInt("CACHE_MEMORY_MAX_ENTRIES", 2_000);
|
const MAX_MEMORY_ENTRIES = readPositiveInt("CACHE_MEMORY_MAX_ENTRIES", 1_000);
|
||||||
|
|
||||||
// Single-flight: a key being (re)computed is awaited by concurrent callers
|
// Single-flight: a key being (re)computed is awaited by concurrent callers
|
||||||
// instead of each starting its own `fn()` (cache-stampede protection).
|
// instead of each starting its own `fn()` (cache-stampede protection).
|
||||||
@@ -62,9 +62,20 @@ const generations = new Map<string, number>();
|
|||||||
const MAX_GENERATION_ENTRIES = MAX_MEMORY_ENTRIES * 2;
|
const MAX_GENERATION_ENTRIES = MAX_MEMORY_ENTRIES * 2;
|
||||||
|
|
||||||
// Keys whose most recent background refresh failed, so a persistently broken
|
// Keys whose most recent background refresh failed, so a persistently broken
|
||||||
// origin reports once instead of on every read of a hot key.
|
// origin reports once instead of on every read of a hot key. Bounded so a
|
||||||
|
// high-cardinality stream of failing keys can never grow this without limit.
|
||||||
|
const MAX_REPORTED_FAILURES = 500;
|
||||||
const reportedFailures = new Set<string>();
|
const reportedFailures = new Set<string>();
|
||||||
|
|
||||||
|
function recordReportedFailure(key: string): void {
|
||||||
|
if (reportedFailures.has(key)) return;
|
||||||
|
if (reportedFailures.size >= MAX_REPORTED_FAILURES) {
|
||||||
|
const oldest = reportedFailures.values().next().value;
|
||||||
|
if (oldest !== undefined) reportedFailures.delete(oldest);
|
||||||
|
}
|
||||||
|
reportedFailures.add(key);
|
||||||
|
}
|
||||||
|
|
||||||
/** Drop a key from the in-process cache (used when an upstream value changes). */
|
/** Drop a key from the in-process cache (used when an upstream value changes). */
|
||||||
export function invalidateMemory(key: string): void {
|
export function invalidateMemory(key: string): void {
|
||||||
generations.set(key, (generations.get(key) ?? 0) + 1);
|
generations.set(key, (generations.get(key) ?? 0) + 1);
|
||||||
@@ -180,7 +191,7 @@ export async function cached<T>(
|
|||||||
// read: a broken origin would otherwise flood the log from a
|
// read: a broken origin would otherwise flood the log from a
|
||||||
// single hot key.
|
// single hot key.
|
||||||
if (reportedFailures.has(key)) return;
|
if (reportedFailures.has(key)) return;
|
||||||
reportedFailures.add(key);
|
recordReportedFailure(key);
|
||||||
logger.warn("[cache] background refresh failed", {
|
logger.warn("[cache] background refresh failed", {
|
||||||
key,
|
key,
|
||||||
error: String(error),
|
error: String(error),
|
||||||
|
|||||||
Reference in new issue
Block a user