Answer every segment of an inbound concatenated message as it arrives (#83)
* Regression tests for answering every inbound segment as it arrives * Answer every segment of an inbound concatenated message as it arrives * Record the segment-by-segment answer in AGENTS.md and README * Regression tests for an empty message_id on deliver_sm_resp * Answer a deliver_sm with the empty message_id SMPP 3.4 makes it * Record Jasmin's refusal of a deliver_sm_resp message_id * Mark the Jasmin multipart deadlock fixed * Regression tests for the architecture review's findings * Give the segment id notation an owner, and every segment a status * Correct what the ids reach and what a lost group tells the application * Regression tests for a group lost to its own octet overrun * Report a group lost to its own overrun, and refuse by the command it arrived on * Keep the docs true about what a segment is answered with * Count only the answered segments of a group lost to an overrun * Report only what a lost group cost, and say which cap bit
This commit is contained in:
+10
-16
@@ -2,6 +2,7 @@ import type { Dlr } from './dlr.ts';
|
||||
import type { MessageState } from './defs/constants.ts';
|
||||
import type { SmppLog } from './log.ts';
|
||||
import { ExpiringGroups } from './expiring-groups.ts';
|
||||
import { parseSegmentId } from './sms-id.ts';
|
||||
|
||||
export type MessageDlr = Dlr & { segments: Dlr[]; smsId: string };
|
||||
|
||||
@@ -18,8 +19,6 @@ type Group = {
|
||||
parts: Map<number, Dlr>;
|
||||
};
|
||||
|
||||
const numbered = /^(.*)-(\d+)$/;
|
||||
|
||||
/**
|
||||
* MESSAGE_STATE is a flat enum, not a ranking — ACCEPTED is 6 where UNDELIVERABLE is 5 — so reducing
|
||||
* on the wire value reports a part-failed message as delivered. Rank it deliberately instead.
|
||||
@@ -43,14 +42,12 @@ function idNumbering(smsIds: string[]): { base: string; parts: Set<number> } | u
|
||||
const parts = new Set<number>();
|
||||
|
||||
for (const smsId of smsIds) {
|
||||
const match = numbered.exec(smsId);
|
||||
const base = match?.[1];
|
||||
const part = match?.[2];
|
||||
const numbering = parseSegmentId(smsId);
|
||||
|
||||
if (base === undefined || part === undefined) return undefined;
|
||||
if (!numbering) return undefined;
|
||||
|
||||
bases.add(base);
|
||||
parts.add(Number(part));
|
||||
bases.add(numbering.base);
|
||||
parts.add(numbering.part);
|
||||
}
|
||||
|
||||
const [base] = bases;
|
||||
@@ -110,18 +107,15 @@ export class DlrMerger {
|
||||
|
||||
if (dlr.intermediate || dlr.smsId === undefined) return undefined;
|
||||
|
||||
const match = numbered.exec(dlr.smsId);
|
||||
const base = match?.[1];
|
||||
const part = match?.[2];
|
||||
const numbering = parseSegmentId(dlr.smsId);
|
||||
|
||||
if (base === undefined || part === undefined) return undefined;
|
||||
if (!numbering) return undefined;
|
||||
|
||||
const { base, part: number } = numbering;
|
||||
const group = this.groups.get(base);
|
||||
|
||||
if (!group) return undefined;
|
||||
|
||||
const number = Number(part);
|
||||
|
||||
if (!group.expected.has(number)) return undefined;
|
||||
|
||||
group.parts.set(number, dlr);
|
||||
@@ -137,8 +131,8 @@ export class DlrMerger {
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.groups.clear();
|
||||
this.spent.clear();
|
||||
this.groups.takeAll();
|
||||
this.spent.takeAll();
|
||||
}
|
||||
|
||||
/** Drops every group past its deadline. Runs before each collect and on its own timer. */
|
||||
|
||||
Reference in New Issue
Block a user