Say once why the hold timer is not unref'd

This commit is contained in:
2026-09-01 10:48:20 +02:00
parent 2c0dfd172f
commit 2fe36fa4e8
3 changed files with 4 additions and 6 deletions
+1 -2
View File
@@ -110,8 +110,7 @@ export class LinkGate {
settle({ err: aborted() }); settle({ err: aborted() });
} }
// Deliberately not unref()'d: a held request is awaited with a destroyed socket and no // Not unref()'d: a held request is awaited with no other handle, so the process would exit unsettled.
// other handle, so an unref'd timer lets the process exit without ever settling it.
if (left > 0) timer = setTimeout(giveUp, left); if (left > 0) timer = setTimeout(giveUp, left);
signal?.addEventListener('abort', onAbort, { once: true }); signal?.addEventListener('abort', onAbort, { once: true });
-2
View File
@@ -829,8 +829,6 @@ describe('LinkGate', () => {
assert.match(held.err?.message ?? '', /did not come back in time/); assert.match(held.err?.message ?? '', /did not come back in time/);
}); });
// A held send is awaited with the socket destroyed, so an unref'd timer here lets a process whose
// only remaining work is that send exit without ever settling it, losing the message silently.
test('holds on a timer that keeps the process alive', async () => { test('holds on a timer that keeps the process alive', async () => {
const gate = new LinkGate({ log: silentLog, timeout: 10_000 }); const gate = new LinkGate({ log: silentLog, timeout: 10_000 });
const timers = (): number => process.getActiveResourcesInfo().filter(name => name === 'Timeout').length; const timers = (): number => process.getActiveResourcesInfo().filter(name => name === 'Timeout').length;
+3 -2
View File
@@ -139,8 +139,9 @@ session message is a change to every call site.
things — `LinkGate.deadline()` and `wait(deadline)` are a two-call protocol whose only failure things — `LinkGate.deadline()` and `wait(deadline)` are a two-call protocol whose only failure
mode is calling `deadline()` inside the loop, which nothing catches; `Session.linkDown()` is mode is calling `deadline()` inside the loop, which nothing catches; `Session.linkDown()` is
read from both sides of the seam; and `UnansweredError` sits in `pending-requests.ts`, which read from both sides of the seam; and `UnansweredError` sits in `pending-requests.ts`, which
never uses it, for the sole edge that makes `send-sms` import that module at all. Every one of these is unpublished, so it is a two-way never uses it, for the sole edge that makes `send-sms` import that module at all. Every one of
door and belongs after 1.0.0. Raised by review, 2026-09-01. these is unpublished, so it is a two-way door and belongs after 1.0.0. Raised by review,
2026-09-01.
- [ ] **Does an intermediate delivery notification deserve to be a `dlr`?** `esm_class` message type - [ ] **Does an intermediate delivery notification deserve to be a `dlr`?** `esm_class` message type
`INTERMEDIATE_DELIVERY` (0x20) is classified as a message today, so a peer that reports `INTERMEDIATE_DELIVERY` (0x20) is classified as a message today, so a peer that reports
non-final states with it hands the application a raw `id:… stat:ENROUTE` text as an inbound non-final states with it hands the application a raw `id:… stat:ENROUTE` text as an inbound