Public: anyone can read this; the crew can change it.
Sentinel: shared:01m23vygyffx5hg2f5vm8r74sr:1p9qyksd9g is past its budget: trevato/forge: "the page with 150 repositories costs a handful of statements, not one per repository" failed on 3 pulls… #9300
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/9299-sentinel-shared-01m23vygyffx5hg2f5vm8r74 → main 3 commits fork
2 files
changed +31
−4
test/helpers/statements.ts +12 −4
| @@ -15,6 +15,11 @@ | ||
| 15 | 15 | * real N+1 costs more in every run, so the minimum still shows it; noise |
| 16 | 16 | * costs more in some runs, so the minimum drops it. |
| 17 | 17 | * |
| 18 | * The waits read `performance.now()`, never `Date.now()`: a test file earlier in | |
| 19 | * the same process that leaves the wall clock frozen (`setSystemTime`, a spy) | |
| 20 | * would otherwise stop `quiet` ever seeing time pass and hang the test for its | |
| 21 | * whole timeout (#9299: 60 s, on three pulls, only beside other files). | |
| 22 | * | |
| 18 | 23 | * `work` must be repeatable: a request for the same page, not a mutation. |
| 19 | 24 | */ |
| 20 | 25 | |
| @@ -50,15 +55,18 @@ async function once( | ||
| 50 | 55 | export async function quiet(db: Database): Promise<void> { |
| 51 | 56 | const door = db as unknown as Door; |
| 52 | 57 | const original = db.query.bind(db); |
| 53 | let last = Date.now(); | |
| 58 | let last = performance.now(); | |
| 54 | 59 | door.query = (sql: string) => { |
| 55 | last = Date.now(); | |
| 60 | last = performance.now(); | |
| 56 | 61 | return original(sql); |
| 57 | 62 | }; |
| 58 | 63 | try { |
| 59 | const started = Date.now(); | |
| 60 | while (Date.now() - last < QUIET_MS && Date.now() - started < GIVE_UP_MS) | |
| 64 | const started = performance.now(); | |
| 65 | for (;;) { | |
| 66 | const now = performance.now(); | |
| 67 | if (now - last >= QUIET_MS || now - started >= GIVE_UP_MS) break; | |
| 61 | 68 | await new Promise((resolve) => setTimeout(resolve, QUIET_MS / 4)); |
| 69 | } | |
| 62 | 70 | } finally { |
| 63 | 71 | door.query = original; |
| 64 | 72 | } |
test/statements-frozen-clock.test.ts added +19
| @@ -0,0 +1,19 @@ | ||
| 1 | /** The statement counter's waits do not hang when an earlier file left the wall clock frozen (#9299). */ | |
| 2 | ||
| 3 | import { Database } from "bun:sqlite"; | |
| 4 | import { afterEach, expect, setSystemTime, test } from "bun:test"; | |
| 5 | import { quiet, statements } from "./helpers/statements.ts"; | |
| 6 | ||
| 7 | afterEach(() => setSystemTime()); | |
| 8 | ||
| 9 | test("quiet and statements return on a frozen wall clock", async () => { | |
| 10 | setSystemTime(new Date("2026-01-01T00:00:00Z")); | |
| 11 | const db = new Database(":memory:"); | |
| 12 | const t0 = performance.now(); | |
| 13 | await quiet(db); | |
| 14 | const n = await statements(db, () => { | |
| 15 | db.query("select 1").get(); | |
| 16 | }); | |
| 17 | expect(n).toBe(1); | |
| 18 | expect(performance.now() - t0).toBeLessThan(2_000); | |
| 19 | }, 10_000); |
new above
offline