Skip to content

test(site-memory): stop racing two clocks in the public-IP timeout bound - #531

Open
Agnik47 wants to merge 1 commit into
agentrhq:mainfrom
Agnik47:fix/flaky-public-ip-timeout-bound
Open

Agnik47 wants to merge 1 commit into
agentrhq:mainfrom
Agnik47:fix/flaky-public-ip-timeout-bound

Conversation

@Agnik47

@Agnik47 Agnik47 commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Problem

src/site-memory/environment.test.tsbounds public-IP lookup and omits the field on timeout asserts a wall-clock floor against the lookup's 2000 ms
AbortSignal.timeout:

expect(Date.now() - started).toBeGreaterThanOrEqual(2000);

The timer that fires the signal and Date.now() are not the same clock source, so
the observed elapsed time can land a millisecond under the configured timeout. This
is flaky by construction, and it has already failed in CI on the Bun compatibility
job:

FAIL src/site-memory/environment.test.ts
  > candidate environment provenance
  > bounds public-IP lookup and omits the field on timeout
AssertionError: expected 1999 to be greater than or equal to 2000

(Seen on the Bun job for #511, a docs/CLI-only PR that cannot affect this code path.)

Fix

Assert the mechanism rather than the clock. The fetch mock already receives the
signal, so capture signal.reason on abort and require it to be a TimeoutError
which only AbortSignal.timeout produces. The < 4000 upper bound stays, so an
unbounded hang is still caught.

This keeps exactly what the test was written to prove — the lookup is bounded by its
own timeout and drops the field rather than propagating — without racing two clocks.

Verification

  • npx vitest run --project unit src/site-memory/environment.test.ts → 6 passed.
  • bun vitest run --project unit src/site-memory/environment.test.ts → 6 passed.
  • Confirmed AbortSignal.timeout(...).reason.name === 'TimeoutError' on both Node
    24 and Bun 1.3.14, so the assertion is safe on the Bun job.
  • Mutation-checked that the assertion is not vacuous: temporarily replaced the
    timeout signal with a manual AbortController aborted after 10 ms, and the test
    failed with expected 'Error' to be 'TimeoutError'. Source restored afterwards.
  • npx tsc --noEmit → clean.
  • npx vitest run --project unit src/site-memory/ → the only remaining failures are
    four pre-existing EPERM: symlink cases in local-store.test.ts, which are a
    local Windows privilege limitation on my machine and pass on CI. Untouched here.

`bounds public-IP lookup and omits the field on timeout` asserted
`Date.now() - started >= 2000` against a 2000ms `AbortSignal.timeout`. The
timer and `Date.now()` are not the same clock source, so the observed
elapsed time can land just under the configured timeout. The Bun
compatibility job has already failed on it:

    AssertionError: expected 1999 to be greater than or equal to 2000

Assert the mechanism instead: capture the abort reason and require it to be
a `TimeoutError`, which only the lookup's own `AbortSignal.timeout` produces.
The upper bound stays, so an unbounded hang is still caught.
@github-actions

Copy link
Copy Markdown
Contributor

🟢 No documentation gap found — high confidence

The pull request only changes tests, lockfiles, generated metadata, or dependency metadata.

This review is advisory and does not block merging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant