Say what a peer did with each receipt segment, and leave no drop unlogged
This commit is contained in:
+16
-6
@@ -21,6 +21,7 @@ export class HeldMessages {
|
||||
private readonly held: ExpiringGroups<PduObject[]>;
|
||||
private readonly idleWaiters = new IdleWaiters();
|
||||
private readonly log: SmppLog;
|
||||
private readonly max: number;
|
||||
|
||||
constructor(options: HeldMessagesOptions) {
|
||||
this.held = new ExpiringGroups({
|
||||
@@ -29,6 +30,7 @@ export class HeldMessages {
|
||||
timeout: options.timeout,
|
||||
});
|
||||
this.log = options.log;
|
||||
this.max = options.max;
|
||||
}
|
||||
|
||||
/** An application that answers no message at all may not grow this without end. */
|
||||
@@ -37,12 +39,10 @@ export class HeldMessages {
|
||||
|
||||
if (key === undefined) return;
|
||||
|
||||
if (this.held.full) {
|
||||
const evicted = this.held.takeOldest();
|
||||
|
||||
if (evicted) {
|
||||
this.log.warn('heldMessages - dropping the message held longest', { seqNr: evicted[0] });
|
||||
}
|
||||
if (this.held.get(key)) {
|
||||
this.log.warn('heldMessages - replacing a message on a re-used sequence number', { seqNr: key });
|
||||
} else if (this.held.full) {
|
||||
this.dropOldest();
|
||||
}
|
||||
|
||||
this.held.set(key, pduObjs);
|
||||
@@ -76,6 +76,16 @@ export class HeldMessages {
|
||||
return this.idleWaiters.wait(() => this.held.size, timeout, signal);
|
||||
}
|
||||
|
||||
private dropOldest(): void {
|
||||
const oldest = this.held.takeOldest();
|
||||
|
||||
if (!oldest) return;
|
||||
|
||||
const [seqNr] = oldest;
|
||||
|
||||
this.log.warn('heldMessages - buffer full, dropping the oldest message', { max: this.max, seqNr });
|
||||
}
|
||||
|
||||
private sweep(): void {
|
||||
const expired = this.held.takeExpired();
|
||||
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ export class IdleWaiters {
|
||||
* Resolves 0 once nothing is left, or with what still is when the timeout or the signal cuts the
|
||||
* wait short. A timeout of 0 waits forever.
|
||||
*/
|
||||
wait(remaining: () => number, timeout: number, signal?: AbortSignal): Promise<number> {
|
||||
wait(remaining: () => number, timeout: number, signal: AbortSignal | undefined): Promise<number> {
|
||||
if (remaining() === 0) return Promise.resolve(0);
|
||||
|
||||
if (signal?.aborted === true) return Promise.resolve(remaining());
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ export class SendWindow {
|
||||
}
|
||||
|
||||
/** Resolves 0 once nothing is left on the wire, or with what still is. */
|
||||
idle(timeout: number, signal?: AbortSignal): Promise<number> {
|
||||
idle(timeout: number, signal: AbortSignal | undefined): Promise<number> {
|
||||
return this.idleWaiters.wait(() => this.unfinished(), timeout, signal);
|
||||
}
|
||||
}
|
||||
|
||||
+23
-15
@@ -137,6 +137,28 @@ function receiptTlvs(smsId: string, status: MessageState): Record<string, TlvInp
|
||||
};
|
||||
}
|
||||
|
||||
function collectReceipt(sent: Result<{ pduObj: PduObject }>[]): SendDlrResult {
|
||||
const pduObjs: PduObject[] = [];
|
||||
let failure: Error | undefined;
|
||||
let unanswered = 0;
|
||||
|
||||
for (const one of sent) {
|
||||
if (one.err) {
|
||||
if (one.err instanceof UnansweredError) unanswered++;
|
||||
|
||||
failure ??= one.err;
|
||||
} else if (one.pduObj.cmdStatus === 'ESME_ROK') {
|
||||
pduObjs.push(one.pduObj);
|
||||
} else {
|
||||
const refusal = one.pduObj.cmdStatus ?? String(one.pduObj.cmdStatusId);
|
||||
|
||||
failure ??= new Error(`deliver_sm refused by the peer: ${refusal}`);
|
||||
}
|
||||
}
|
||||
|
||||
return failure ? { err: failure, pduObjs, unanswered } : { pduObjs, unanswered };
|
||||
}
|
||||
|
||||
async function sendDlr(
|
||||
sms: Sms,
|
||||
send: SmsHandlers['send'],
|
||||
@@ -166,19 +188,5 @@ async function sendDlr(
|
||||
...(sms.session.acceptsOptionalParams() ? { tlvs: receiptTlvs(smsId, status) } : {}),
|
||||
});
|
||||
}));
|
||||
const pduObjs: PduObject[] = [];
|
||||
let failure: Error | undefined;
|
||||
let unanswered = 0;
|
||||
|
||||
for (const one of sent) {
|
||||
if (!one.err) {
|
||||
pduObjs.push(one.pduObj);
|
||||
} else {
|
||||
if (one.err instanceof UnansweredError) unanswered++;
|
||||
|
||||
failure ??= one.err;
|
||||
}
|
||||
}
|
||||
|
||||
return failure ? { err: failure, pduObjs, unanswered } : { pduObjs, unanswered };
|
||||
return collectReceipt(sent);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user