Skip to content

Dedup test-realm lifecycle hooks + contention-proof hook timeout - #7

Merged
GraemeF merged 1 commit into
mainfrom
comms-xwqm
Jun 13, 2026
Merged

GraemeF merged 1 commit into
mainfrom
comms-xwqm

Conversation

@GraemeF

@GraemeF GraemeF commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

What

The non-live test suite intermittently failed on cache-miss / pre-commit runs. Reproduced under concurrent-suite contention (a proxy for the full-parallel bun run check load): the failures were always "a beforeEach/afterEach hook timed out", never a test-body timeout.

Root cause: bun's lifecycle hooks keep their own 5s timeout, independent of a test's per-test timeout. Real in-process-realm setup/teardown runs in a few ms in isolation, but under a starved event loop it stretches past 5s — and the hook, not the body, times out, landing the failure on whichever test the hook happened to wrap (which is why the failing test name moved run-to-run, and why the earlier per-test-body 30s bump didn't help).

How

Extract one shared registerRealmHooks(start, assign) + REALM_HOOK_TIMEOUT_MS in packages/testing/realm-hooks.ts:

  • The realm beforeEach/afterEach boilerplate in adapter.test.ts and bot-dm-guard.test.ts was byte-identical; http.test.ts is the same shape with a fixture; the contract suite is a third (async factory / Effect dispose) variant. All now route through the shared helper / constant.
  • The assign callback hands the fresh instance back to each file's own let binding, so the ~170 realm./fixture. call sites are untouched — no getter churn.

So this both removes the duplication and gives the hooks the headroom the per-test bodies already had.

Known residual (deferred)

This is headroom, not a full cure. The two infinite-long-poll teardown tests (gap-replay comms-4au, scope-close-interrupt spj3.8) can still exceed even 30s under aggressive contention. That residual is a fiber/scope lifecycle problem — server.stop(true) is provably not the blocker (an isolated probe resolves it in 0.2ms with a handler stuck forever and the client aborted). It's tracked for the Effect-Scope-based realm rework (comms-4lz5 / comms-30hq), where running the whole test inside one scope with guaranteed finalizers removes the leftover-fiber-starves-teardown mode structurally.

The non-live suite intermittently failed on cache-miss runs (comms-xwqm):
under a full-parallel `bun run check` the starved event loop stretched
real-in-process-realm setup/teardown past bun's default 5s HOOK timeout —
independent of the per-test body timeout the gap-replay test already
raised — so the failure landed on whichever test the slow hook wrapped,
explaining the moving test name.

Extract one shared `registerRealmHooks(start, assign)` + `REALM_HOOK_TIMEOUT_MS`
(packages/testing/realm-hooks.ts). The byte-identical realm beforeEach/afterEach
boilerplate in adapter.test.ts and bot-dm-guard.test.ts, the same-shaped
fixture hooks in http.test.ts, and the contract suite's factory/dispose hooks
all route through it. The `assign` callback hands the instance back to each
file's own `let` binding, so the ~170 `realm.`/`fixture.` call sites stay
untouched. contract.ts (async factory / Effect dispose) just imports the
timeout constant.

This is headroom, not a full cure: the two infinite-long-poll teardown tests
(gap-replay comms-4au, scope-close-interrupt spj3.8) can still exceed even 30s
under aggressive contention. That residual is a fiber/scope lifecycle problem
(server.stop(true) is not the blocker — an isolated probe resolves it in 0.2ms
with a handler stuck forever), tracked for the Effect-Scope-based realm rework
in comms-4lz5 / comms-30hq.
@GraemeF
GraemeF merged commit afcbd97 into main Jun 13, 2026
2 checks passed
@GraemeF
GraemeF deleted the comms-xwqm branch June 13, 2026 08:22
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