Name carry()'s retry condition and what ends its loop
Test / lint (pull_request) Successful in 23s
Mirror / push (push) Has been cancelled
Test / test (22) (pull_request) Successful in 32s
Test / test (24) (pull_request) Successful in 31s
Test / test (18) (pull_request) Successful in 31s
Test / test (20) (pull_request) Successful in 30s
Test / test (26) (pull_request) Successful in 32s

This commit is contained in:
2026-09-28 01:45:31 +02:00
parent bfd0ed1b98
commit 696562daec
6 changed files with 33 additions and 13 deletions
+5
View File
@@ -42,6 +42,11 @@ export class LinkGate {
return this.up;
}
/** Shut, with another link on its way to reopen it. */
awaitsNextLink(): boolean {
return !this.up && this.returning;
}
/** Why the gate will never admit a request, or undefined while one may still get through. */
refusal(): Error | undefined {
return this.up || this.returning ? undefined : over();
+13 -5
View File
@@ -93,11 +93,14 @@ export class OutgoingRequests {
return Promise.resolve({ err: new Error('Session is shutting down') });
}
return this.pastDrain(input, options);
return this.carry(input, options);
}
/** The same path without that refusal, which a receipt for a held message has to take. */
async pastDrain(
/**
* The same path without the drain's refusal, which a receipt for a held message has to take.
* It ends with the first attempt that reached the socket, or once no next link will carry it.
*/
async carry(
input: PduObjectInput,
options: SendOptions,
): Promise<Result<{ pduObj: PduObject }>> {
@@ -125,8 +128,7 @@ export class OutgoingRequests {
const attempt = await this.attempt(input, options).finally(() => { this.window.release(); });
// Nothing reached the socket, so the next link carries it instead of the caller resending.
if (!attempt.retryOnNextLink || this.gate.isUp() || this.gate.refusal()) return attempt.result;
if (!this.retriesOnNextLink(attempt)) return attempt.result;
}
}
@@ -151,6 +153,12 @@ export class OutgoingRequests {
return { err: new Error(`Shut down with ${String(unfinished)} request(s) unfinished`) };
}
/** Nothing reached the socket, so the next link carries it instead of the caller resending. */
private retriesOnNextLink(attempt: Attempt): boolean {
// Until the gate is shut it admits the retry straight back onto the dead socket, and the loop spins.
return attempt.retryOnNextLink && this.gate.awaitsNextLink();
}
/** Why a request cannot go out at all, as opposed to not yet. */
private refuse(input: PduObjectInput, options: SendOptions): Error | undefined {
// Before the gate and the window, or an aborted call waits for what it will never use.
+1 -1
View File
@@ -261,7 +261,7 @@ export class Session extends EventEmitter<SessionEvents> {
reportError: err => { this.emit('sessionError', err); },
reportMessageDlr: merged => { this.emit('messageDlr', merged); },
send: input => this.send(input),
sendPastDrain: input => this.outgoing.pastDrain(input, {}),
sendPastDrain: input => this.outgoing.carry(input, {}),
smsListeners: () => this.listenerCount('sms'),
};
}