Give the link's liveness one owner
Test / lint (pull_request) Successful in 24s
Test / test (18) (pull_request) Successful in 32s
Test / test (20) (pull_request) Successful in 32s
Test / test (22) (pull_request) Successful in 32s
Test / test (24) (pull_request) Successful in 32s
Mirror / push (push) Has been cancelled
Test / test (26) (pull_request) Successful in 32s
Test / lint (pull_request) Successful in 24s
Test / test (18) (pull_request) Successful in 32s
Test / test (20) (pull_request) Successful in 32s
Test / test (22) (pull_request) Successful in 32s
Test / test (24) (pull_request) Successful in 32s
Mirror / push (push) Has been cancelled
Test / test (26) (pull_request) Successful in 32s
This commit is contained in:
+12
-10
@@ -508,9 +508,9 @@ rule and an index of the titles below.
|
||||
|
||||
- **`close` means the session is over, and a drop the loop will retry is `disconnected`.**
|
||||
Maintainer's call, 2026-08-31: without the split, an application that opens a replacement client on
|
||||
`close` ends up holding two binds on one account. `teardown()` picks the event by whether the
|
||||
reconnect loop is still live, and `end()` stops that loop before tearing down, so every deliberate
|
||||
shutdown emits `close`. A retry that opens a socket and then loses it resets `lifecycle` through
|
||||
`close` ends up holding two binds on one account. `teardown()` picks the event by
|
||||
`LinkLife.retrying()`, and `end()` stops the session before tearing down, so every deliberate
|
||||
shutdown emits `close`. A retry that opens a socket and then loses it is attached again through
|
||||
`attach()`, which is why a second drop emits again.
|
||||
|
||||
- **An answer belongs to the link the message arrived on; a receipt does not.** Maintainer's call,
|
||||
@@ -542,7 +542,7 @@ rule and an index of the titles below.
|
||||
rate goal 4 cares about. The attempts before the first link report nothing, because the session
|
||||
running one has not reached the application: `disconnected` would have no listener and `close`
|
||||
would be a lie. Its wait is the one retry timer that is not `unref()`'d, for the reason
|
||||
`LinkGate`'s hold is not — it is awaited with no other handle, so a process whose only work is
|
||||
`LinkLife`'s hold is not — it is awaited with no other handle, so a process whose only work is
|
||||
`client()` would exit unbound.
|
||||
|
||||
- **`connectTimeout` defaults to 10 s, bounds the whole connect including the TLS handshake, and
|
||||
@@ -760,15 +760,17 @@ rule and an index of the titles below.
|
||||
an abort at the gate already gives. The drain half needs nothing: `close({ signal })` already hands the signal to
|
||||
`window.idle()`, and `unbind()` taking none is the shape README states.
|
||||
|
||||
- **The gate decides whether a link can carry a request, and a bind is what makes it one.**
|
||||
- **`LinkLife` decides whether a link can carry a request, and a bind is what makes it one.**
|
||||
Maintainer's call, 2026-09-01: `attach()` marks the session attached the moment a socket is
|
||||
handed over, one round trip before the bind is answered, so gating on that let a send arriving in
|
||||
that window go out unbound and come back `ESME_RINVBNDSTS`. The gate is told what happened and
|
||||
that window go out unbound and come back `ESME_RINVBNDSTS`. `LinkLife` is told what happened and
|
||||
never reads back into the session: a collaborator that has to ask does not own its decision, which
|
||||
is how the first cut ended up answering the same question two different ways at admit and at
|
||||
release. The retry in `requestPastDrain()` asks `gate.awaitsNextLink()` rather than `canCarry()`,
|
||||
which also reads the socket: a loop condition the gate does not gate on spins against a gate that
|
||||
admits it straight back.
|
||||
release. Every other collaborator reads whether the link lives from it and keeps no copy: five
|
||||
copies held in step by statement order were what the 2026-09-28 comprehension runs ranked hardest.
|
||||
The retry in `requestPastDrain()` asks `link.awaitsNextLink()` rather than `canCarry()`, which also
|
||||
reads the socket: a loop condition the link does not gate on spins against a link that admits it
|
||||
straight back.
|
||||
|
||||
|
||||
## Internals and tests
|
||||
@@ -790,7 +792,7 @@ rule and an index of the titles below.
|
||||
handlers normalise through `errorFrom()` rather than inline — a route out of the handler would land
|
||||
on a bare `process.nextTick` with nothing to catch it.
|
||||
|
||||
- **The four-line abort dance is copied across `LinkGate`, `IdleWaiters`, `PendingRequests` and
|
||||
- **The four-line abort dance is copied across `LinkLife`, `IdleWaiters`, `PendingRequests` and
|
||||
`SendWindow` rather than extracted.** Architecture review, 2026-09-06: pre-check `aborted`, attach
|
||||
`{ once: true }`, detach on settle, leave the registry. What differs at each site is the registry
|
||||
and what settling means — a FIFO handing over a slot, a set released together, a map keyed by
|
||||
|
||||
Reference in New Issue
Block a user