Name the loop's own flag, and drop droppedWhileDraining()
Mirror / push (push) Successful in 6s
Test / lint (pull_request) Successful in 27s
Test / test (18) (pull_request) Successful in 32s
Test / test (20) (pull_request) Successful in 31s
Test / test (22) (pull_request) Successful in 32s
Test / test (24) (pull_request) Successful in 32s
Test / test (26) (pull_request) Successful in 32s

This commit is contained in:
2026-09-28 21:27:00 +02:00
parent cce1d7c02e
commit 2152b995d4
4 changed files with 8 additions and 10 deletions
+2
View File
@@ -768,6 +768,8 @@ rule and an index of the titles below.
is how the first cut ended up answering the same question two different ways at admit and at is how the first cut ended up answering the same question two different ways at admit and at
release. Every other collaborator reads whether the link lives from it and keeps no copy: five 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. copies held in step by statement order were what the 2026-09-28 comprehension runs ranked hardest.
`ReconnectLoop.halted` is the loop's own, for its timer, because `client()` also runs a loop with
no session behind it for `fromStart`; a session's loop is stopped by `Session.stop()` alone.
The retry in `requestPastDrain()` asks `link.awaitsNextLink()` rather than `canCarry()`, which also 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 reads the socket: a loop condition the link does not gate on spins against a link that admits it
straight back. straight back.
+3 -3
View File
@@ -59,9 +59,9 @@ export class LinkLife {
return this.phase === 'ended'; return this.phase === 'ended';
} }
/** False once the session is shutting down: nothing new is taken, and no link follows this one. */ /** The session is shutting down: nothing new is taken, and no link follows this one. */
isAccepting(): boolean { isStopped(): boolean {
return !this.stopped; return this.stopped;
} }
/** Whether a link that drops now is followed by another. */ /** Whether a link that drops now is followed by another. */
+1 -6
View File
@@ -54,11 +54,6 @@ export class OutgoingRequests {
return this.link.isUp() && !this.transport.sock.destroyed; return this.link.isUp() && !this.transport.sock.destroyed;
} }
/** The link went before the drain finished, so an empty window says nothing about the peer. */
droppedWhileDraining(): boolean {
return !this.link.isAccepting() && !this.canCarry();
}
/** The link is gone, and every answer still owed on it with it. */ /** The link is gone, and every answer still owed on it with it. */
linkLost(): void { linkLost(): void {
this.pending.settleAll(new Error('Session closed before a response arrived')); this.pending.settleAll(new Error('Session closed before a response arrived'));
@@ -82,7 +77,7 @@ export class OutgoingRequests {
if (wrong) return Promise.resolve({ err: wrong }); if (wrong) return Promise.resolve({ err: wrong });
// With no link, the request is refused as closed further on. // With no link, the request is refused as closed further on.
if (!this.link.isAccepting() && this.canCarry()) { if (this.link.isStopped() && this.canCarry()) {
return Promise.resolve({ err: new Error('Session is shutting down') }); return Promise.resolve({ err: new Error('Session is shutting down') });
} }
+2 -1
View File
@@ -333,7 +333,8 @@ export class Session extends EventEmitter<SessionEvents> {
const messages = await this.incoming.drain(this.answering(timeout), signal); const messages = await this.incoming.drain(this.answering(timeout), signal);
const requests = await this.outgoing.drain(leftOf(deadline), signal); const requests = await this.outgoing.drain(leftOf(deadline), signal);
if (this.outgoing.droppedWhileDraining()) { // The link went before the drain finished, so an empty window says nothing about the peer.
if (!this.outgoing.canCarry()) {
return { err: new Error('The session closed before the drain finished') }; return { err: new Error('The session closed before the drain finished') };
} }