refactor(remote): drop the vacuous intentional-close check in PocketClient - #410
Conversation
…lient The generation guard already rejects every close that is not the live socket's, so the null check below it was unconditionally true and its comment described a mechanism no longer in play.
Deploying mouseterm with
|
| Latest commit: |
a300b39
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://0b618eeb.mouseterm.pages.dev |
| Branch Preview URL: | https://fix-pocket-close-dead-guard.mouseterm.pages.dev |
dormouse-bot
left a comment
There was a problem hiding this comment.
The vacuousness argument holds: #onClose(ws: PocketSocket) takes a non-nullable socket, so past if (this.#ws !== ws) return; we have this.#ws === ws with ws non-null, making this.#ws !== null unconditionally true. notifyGone reduces to #connectedHostId !== null on every reachable path, and the four socket lifecycle tests pin all of them. The Host-side twin in remote-host.ts (if (this.#ws !== ws) return; inside its close listener) never grew the same redundant term, so there's no second instance to clean up.
One thing the change leaves behind. close() still carries the sibling comment describing the mechanism this PR just deleted:
// Tear down BEFORE closing the socket: #onClose reads `#ws === null` as an
// intentional close (no host-gone), and while real sockets emit their close
// event asynchronously, test fakes may emit it synchronously from close().
#onClose no longer reads #ws === null anywhere — the teardown-before-close ordering now matters because nulling #ws makes the generation guard reject the close, which after this PR is the sole thing keeping an intentional close() from firing onHostGone. That makes the ordering constraint more load-bearing than it was, while its only explanation now points at a check that isn't in the file. A reader who greps for #ws === null in #onClose and comes up empty could reasonably conclude the ordering no longer matters and move the ws?.close() above the teardown, which would resurrect the bug in the closeEmits synchronous-fake case the comment's second clause is warning about.
It's outside the diff, so I've pushed the comment rewrite as a follow-up commit rather than leaving an inline suggestion. Nothing else to flag — no behavior delta, and no spec covers this branch (docs/specs/server.md's only host-gone mention is the Host-displacement paragraph, which is about the relay, not the client's close handling).
close() tore down before ws.close() because #onClose read `#ws === null` as an intentional close. That read is gone; the ordering now matters because nulling #ws is what makes the generation guard reject the close, which is the sole thing keeping an intentional close from firing host-gone. Describe the mechanism that is actually there.
PocketClient.#onClosedecides whether a closed relay socket should fireonHostGone, and it still computes that decision two ways. The generation guard added in499123dd("Fix stale Pocket socket events") already rejects every close that isn't the live socket's — an intentionalclose()nulls#wsbefore callingws.close(), and a reconnect overwrites it — so by the time control reaches the next line,this.#ws === wsandthis.#ws !== nullis unconditionallytrue. The comment above it still explains the superseded null-check mechanism as the thing distinguishing an intentional close from a drop, which is no longer where that decision is made.This drops the vacuous
unexpectedterm and moves the comment onto the guard that actually does the work. No behavior change:notifyGoneis nowthis.#connectedHostId !== null, which is whatunexpected && hadSessionalready evaluated to on every reachable path.No new regression test — this is a refactor with no behavior delta, and all four branches are already pinned by the existing
socket lifecyclesuite: unexpected drop with a session fireshost-gone, intentionalclose()doesn't, an unexpected drop without a session is silent, and a stale socket's close is ignored entirely.Verification
Checked against
92608bb5:corepack pnpm --filter dormouse-lib exec vitest run src/remote/client/pocket-client.test.ts→ 30 passed.corepack pnpm --filter dormouse-lib exec tsc --noEmit→ clean.pocket-client.test.ts#L661,#L673,#L696,#L707.grep 'host-gone\|onHostGone' docs/specs/only matches the Host-displacement paragraph inserver.md), so nothing to update above the fold.Surfaced by the nightly rolling survey.