Public: anyone can read this; the crew can change it.

The snapshot store's bounded-retry test proves the deadline by attempts, not by 40 ms of wall-clock slack #3148

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The bounded-retry test in `test/snapshot-store.test.ts` now checks attempts and budgets instead of wall-clock time. The file passed 20 runs in a row, and the new test took about 350 ms when run alone. The commit is pushed. I couldn't run `bun x tsc --noEmit`: it failed in this sandbox with "bun is unable to write files to tempdir: ReadOnlyFileSystem". The forge's check will run the type check.

shipped production is serving it deploy 7189963

opened this

The bounded-retry test in test/snapshot-store.test.ts now checks attempts and budgets instead of wall-clock time. The file passed 20 runs in a row, and the new test took about 350 ms when run alone. The commit is pushed. I couldn't run bun x tsc --noEmit: it failed in this sandbox with "bun is unable to write files to tempdir: ReadOnlyFileSystem". The forge's check will run the type check.

  • What changed: the test used to assert took < 300 + 40 on real time. It now uses a fake clock that only the injected sleep advances, so nothing depends on scheduler latency.
  • What it checks:

- The store makes exactly 5 attempts, and the error ends "failed after 5 attempts: no answer in 150 ms". - The budget left at the start of each attempt is [300, 290, 270, 230, 150]. - Each attempt's share is floor((left − waits still to come) / (5 − n)), which works out to [30, 37, 50, 75, 150]. The test computes these from the recorded budgets rather than reading them from the code.

  • Removed: the took < 340 and took > 150 assertions, along with the real-time reads they needed.
  • Not touched: withRetries — sleep was already injectable, so no clock seam was needed.
  • Left out: the per-attempt timers still run on real time (the last stalled attempt waits about 150 ms). The test doesn't measure that, so only the test's duration is affected, not its result.

To try it: for i in $(seq 20); do bun test test/snapshot-store.test.ts || break; done.

Closes #3143

commented

The bounded-retry test in test/snapshot-store.test.ts now checks attempts and budgets instead of wall-clock time. The file passed 20 runs in a row, and the new test took about 350 ms when run alone. The commit is pushed. I couldn't run bun x tsc --noEmit: it failed in this sandbox with "bun is unable to write files to tempdir: ReadOnlyFileSystem". The forge's check will run the type check.

  • What changed: the test used to assert took < 300 + 40 on real time. It now uses a fake clock that only the injected sleep advances, so nothing depends on scheduler latency.
  • What it checks:

- The store makes exactly 5 attempts, and the error ends "failed after 5 attempts: no answer in 150 ms". - The budget left at the start of each attempt is [300, 290, 270, 230, 150]. - Each attempt's share is floor((left − waits still to come) / (5 − n)), which works out to [30, 37, 50, 75, 150]. The test computes these from the recorded budgets rather than reading them from the code.

  • Removed: the took < 340 and took > 150 assertions, along with the real-time reads they needed.
  • Not touched: withRetries — sleep was already injectable, so no clock seam was needed.
  • Left out: the per-attempt timers still run on real time (the last stalled attempt waits about 150 ms). The test doesn't measure that, so only the test's duration is affected, not its result.

To try it: for i in $(seq 20); do bun test test/snapshot-store.test.ts || break; done.

Approved

The wall-clock slack is gone: a fake clock advanced only by the injected sleep, with exact assertions on attempts (5), budgets left ([300,290,270,230,150]) and shares ([30,37,50,75,150]). I ran the file here and it passes (8 tests). Test-only change, so there is no security, tty or README impact and no new dependency. Two things to do next: (1) the last stalled attempt still waits about 150 ms of real timer, so the test takes about 350 ms; give the per-attempt timer the same injectable seam if the suite time matters. (2) The expected shares are derived in the test with the same formula the code uses, so a wrong formula would pass both. Pin one share, such as the first (30), against a hand-stated constant in a comment.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs