testing: real-socket scope-close TCP teardown test (comms-4lz5) - #15
Merged
Merged
Conversation
The Tier-3 residue of the hexagonal test-architecture epic: the one assertion that genuinely cannot leave the socket — interrupting an in-flight FetchHttpClient long-poll on scope close actually tears down the underlying TCP connection (AbortSignal -> fetch -> socket). comms-e5vm.2 moved every event-pump LOGIC test (gap-replay, 429 retry, BAD_EVENT_QUEUE_ID reconnect, the Effect fiber-interrupt path of scope close) onto the stub HttpClient + TestClock — deterministic, no socket. The stub proves the fiber unwinds; it cannot prove the socket unwinds. This test closes that gap and is the only surviving Bun.serve long-poll. The assertion is server-side: a real Bun.serve whose long-poll handler parks forever but listens on req.signal, so observing the abort proves the teardown reached the peer rather than just unwinding our fiber. Lifecycle is Effect.acquireRelease/Scope throughout. Also refreshes the realm-hooks doc comment, whose forward-reference to this bead described a teardown-starvation mode that .2 dissolved.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Tier-3 residue of the hexagonal test-architecture epic (comms-e5vm): the one assertion in the suite that genuinely cannot leave the socket — that interrupting an in-flight `FetchHttpClient` long-poll on scope close actually tears down the underlying TCP connection (`AbortSignal → fetch → socket`).
Why this is the only surviving socket test
comms-e5vm.2 (#12) moved every event-pump LOGIC test — gap-replay, 429 retry, BAD_EVENT_QUEUE_ID reconnect, and the Effect fiber-interrupt path of scope close — onto the owned-fake stub HttpClient + TestClock: deterministic, no socket. The stub proves the fiber unwinds. It cannot prove the socket unwinds, because there is no socket. This test closes exactly that gap and is the only surviving `Bun.serve` long-poll in the suite.
The assertion is server-side
A real `Bun.serve` whose long-poll handler parks forever but listens on the request's `req.signal`. When the client tears the connection down, Bun fires that abort — observing it is proof the teardown reached the peer, not merely that our Effect fiber unwound (which the stub already covers). The Effect platform client wires this end to end: `httpClient.make` aborts the request's `AbortController` `onInterrupt`, and `FetchHttpClient` passes that `signal` into `fetch`.
Lifecycle is `Effect.acquireRelease`/`Scope` throughout: the server's release is `server.stop(true)`, and the long-poll is forked into an inner `Effect.scoped` whose close is the interruption under test — so release is guaranteed even on the interruption path. The proof is timeout-guarded, so a non-teardown fails loud (verified by a mutation: detaching the fiber from the scope makes the test time out).
Broader-rework question (comms-4lz5's original scope): recommend leave-as-is
The bead also asked whether to migrate the ~170 `realm.`/`fixture.` hook call sites to a per-test `Effect.scoped` wrapper. That rework was motivated by a contention-driven teardown-starvation flake in the infinite-long-poll tests — which .2 dissolved structurally by moving that logic off the socket. Every fixture still wired through `registerRealmHooks` is now a plain request/response realm that starts and stops in a few ms; there is no teardown-starvation mode left to fix, and the `acquireRelease`/`Scope` shape now lives exactly where it is load-bearing (this one socket test). The migration would be churn across ~170 sites for no behavioural payoff — YAGNI. This PR also refreshes the now-stale `realm-hooks.ts` doc comment that still described the dissolved failure mode.
Closes comms-4lz5.