diff --git a/src/held-messages.ts b/src/held-messages.ts index 5346b95..a952835 100644 --- a/src/held-messages.ts +++ b/src/held-messages.ts @@ -40,25 +40,25 @@ type HoldRoute = Pick */ export class MessageHold implements SmsHandlers { private readonly generation: number; + private readonly heldMessages: HeldMessages; private readonly pduObjs: PduObject[]; private readonly route: HoldRoute; - private readonly store: HeldMessages; private working: number; - constructor(store: HeldMessages, route: HoldRoute, pduObjs: PduObject[], listeners: number) { + constructor(heldMessages: HeldMessages, route: HoldRoute, pduObjs: PduObject[], listeners: number) { this.generation = route.link.generation(); + this.heldMessages = heldMessages; this.pduObjs = pduObjs; this.route = route; - this.store = store; this.working = listeners; } /** Whether a drain is still waiting for this message to be answered. */ isHeld(): boolean { - return this.store.holds(this.pduObjs); + return this.heldMessages.holds(this.pduObjs); } - /** A turn later, so a listener sending its receipt straight after the response still holds. */ + /** A turn later, so a `sendDlr()` called straight after `sendResp()` still goes out past a drain. */ answered(): void { setImmediate(() => { this.release(); }); } @@ -76,7 +76,7 @@ export class MessageHold implements SmsHandlers { /** At once, for a message nobody took or a listener threw on: that is not work a shutdown can wait for. */ release(): void { - this.store.release(this.pduObjs); + this.heldMessages.release(this.pduObjs); } /** A receipt for a message still held is what a drain waits for, so it goes out past the drain. */ @@ -160,14 +160,14 @@ export class HeldMessages { this.offered.get(message)?.listenerGaveUp(); } - /** For `MessageHold`, which is how everything else asks. */ + /** Called by `MessageHold`; everything else asks the hold. */ holds(pduObjs: PduObject[]): boolean { const key = keyOf(pduObjs); return key !== undefined && this.held.get(key) === pduObjs; } - /** For `MessageHold`, which is how everything else releases. */ + /** Called by `MessageHold`; everything else releases through the hold. */ release(pduObjs: PduObject[]): void { const key = keyOf(pduObjs); diff --git a/todo.md b/todo.md index 4960d3d..f70527e 100644 --- a/todo.md +++ b/todo.md @@ -205,6 +205,11 @@ after #46, read 6, 6, 7 and 7, Locality 5, 5, 6 and 6. A fourth, after the link' owner in #48, read 6, 6, 6 and 6, Locality 5 from every seat: all four still ranked `Session.teardown()` hardest, and the held-message flow across `incoming-requests.ts`, `held-messages.ts`, `sms.ts` and `Session`'s rejection handler second. +A fifth, after the held-message flow got one owner, read 6, 6, 7 and 6, Locality 5, 5, 6 and 6: +three seats still ranked `MessageHold` hardest — six ways out, a rejection routed from `Session` +through `IncomingRequests` to a `WeakMap`, and the `setImmediate` a receipt relies on — and the +teardown cluster second; the inherited architect scored Shape 5 on the flat `src/` and the names +below. - [ ] **Lift Locality to 7, and confirm it with a scoring run.** A run reading 7.0 or above also retires the #30, #46 and #48 decision. @@ -317,10 +322,16 @@ hardest, and the held-message flow across `incoming-requests.ts`, `held-messages - [ ] **Collapse the three objects named `defaults`.** `client.ts`, `server.ts` and `session-options.ts` each export or hold one; `port: 2775` is written twice and the idle - timeout is derived two ways to the same 40 000. "What is the default for X" has three answers + timeout is derived two ways to the same 40 000, and 64 MiB is both `defaultMaxOctets` and + `defaults.maxHeldOctets`. "What is the default for X" has three answers depending on the entrypoint, and nothing fails when they drift. Named by both architects as the most likely first bug a new contributor ships. +- [ ] **Give `hold` one meaning, and rename `IncomingRequests.refusing` for what it does.** + `LinkLife.hold()` is a request's budget waiting for a link, `HeldMessages.hold()` a message the + application owes an answer; `refusing` decides no refusal — `held.full()` does — and only makes + the warn and info lines fire once each way. From the 2026-09-29 scoring run. + - [ ] **Rename `EncodingName`'s `ASCII` to `GSM7`, with `ASCII` a deprecated alias for one minor.** It is GSM 03.38, where `$` is 0x02 and `@` is 0x00, and `segmentUnits.ASCII = 153` is a septet budget under a name that says octets. The 2026-09-09 decision removed `consts.ENCODING.ASCII`