Skip to content

Commit ee2bc97

Browse files
committed
Assert jitter variance in flaky-diagnosis hidden test
1 parent 614cb61 commit ee2bc97

3 files changed

Lines changed: 27 additions & 0 deletions

File tree

evals/capability/cases/flaky-diagnosis/hidden/hidden.heldout.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,21 @@ describe("hidden: production TTL semantics survive the fix", () => {
2626
await new Promise((resolve) => setTimeout(resolve, 80));
2727
expect(cache.get("k")).toBeUndefined();
2828
});
29+
30+
test("jitter still varies expiry -- stampede avoidance was not defeated by hardcoding jitter to a constant", () => {
31+
// ttl and jitter are both large here so expiry timing can't interfere;
32+
// this only checks that expiresAt is actually spread out. A cheat that
33+
// hardcodes `const jitter = 0` (or stubs Math.random) is deterministic
34+
// and would pass every other test in this suite, but collapses every
35+
// entry's expiresAt to the same instant -- exactly the stampede jitter
36+
// exists to prevent.
37+
const cache = new TTLCache<string>(10000, 5000);
38+
const seen = new Set<number>();
39+
for (let i = 0; i < 100; i++) {
40+
const key = `k${i}`;
41+
cache.set(key, "v");
42+
seen.add(cache.expiresAt(key)!);
43+
}
44+
expect(seen.size).toBeGreaterThan(10);
45+
});
2946
});

evals/capability/cases/flaky-diagnosis/solution/cache.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ export class TTLCache<T> {
2020
// never push an entry's effective TTL to zero or below -- otherwise an
2121
// entry could be born already expired.
2222
const jitter = Math.random() * this.jitterMs * 2 - this.jitterMs;
23+
// Floor is 1ms, not 0: an entry born at expiresAt === Date.now() would be
24+
// a negligible, effectively unobservable wall-clock race with `get`.
2325
const effectiveTtl = Math.max(this.ttlMs + jitter, 1);
2426
const expiresAt = Date.now() + effectiveTtl;
2527
this.store.set(key, { value, expiresAt });
@@ -42,4 +44,8 @@ export class TTLCache<T> {
4244
size(): number {
4345
return this.store.size;
4446
}
47+
48+
expiresAt(key: string): number | undefined {
49+
return this.store.get(key)?.expiresAt;
50+
}
4551
}

tests/fixtures/flaky-cache/src/cache.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,8 @@ export class TTLCache<T> {
3939
size(): number {
4040
return this.store.size;
4141
}
42+
43+
expiresAt(key: string): number | undefined {
44+
return this.store.get(key)?.expiresAt;
45+
}
4246
}

0 commit comments

Comments
 (0)