fix: correlate downstream receipts with submit responses

This commit is contained in:
hectorzhao
2026-07-14 16:22:41 +08:00
parent 135b4fd24e
commit 1ce02ef206
12 changed files with 487 additions and 91 deletions
+24 -4
View File
@@ -119,7 +119,7 @@ export interface GatewayDownstreamAcknowledgedDto extends GatewayDownstreamSentD
acknowledgedAt?: string;
}
export type GatewayDownstreamFailureType = 'send_failed' | 'ack_timeout' | 'ack_rejected' | 'connection_lost';
export type GatewayDownstreamFailureType = 'send_failed' | 'ack_timeout' | 'ack_rejected' | 'ack_invalid' | 'connection_lost';
type GatewayControlDeliveryResult = {
sent?: boolean;
@@ -987,7 +987,8 @@ export class SendChainService implements OnModuleInit, OnModuleDestroy {
async acknowledgeDownstreamDelivery(data: GatewayDownstreamAcknowledgedDto) {
const acknowledgedAt = asDateOrNull(data.acknowledgedAt) ?? new Date();
if (data.result === 0) {
const acknowledgedMessageId = String(data.messageId ?? '').trim();
if (data.result === 0 && acknowledgedMessageId !== '' && acknowledgedMessageId !== '0') {
await this.prisma.cmppDownstreamDelivery.updateMany({
where: { id: data.id, status: { not: 'delivered' } },
data: {
@@ -1015,6 +1016,9 @@ export class SendChainService implements OnModuleInit, OnModuleDestroy {
connectionId: data.connectionId,
},
});
if (data.result === 0) {
return this.markDownstreamDeliveryFailed(data.id, 'CMPP_DELIVER_RESP Msg_Id=0,客户端仅确认协议收包,无法关联原短信', 'ack_invalid');
}
return this.markDownstreamDeliveryFailed(data.id, `downstream CMPP_DELIVER_RESP result=${data.result}`, 'ack_rejected');
}
@@ -1027,7 +1031,7 @@ export class SendChainService implements OnModuleInit, OnModuleDestroy {
return delivery;
}
const retryCount = (delivery.retryCount ?? 0) + 1;
const acknowledgementFailure = failureType === 'ack_timeout' || failureType === 'ack_rejected' || failureType === 'connection_lost';
const acknowledgementFailure = failureType === 'ack_timeout' || failureType === 'ack_rejected' || failureType === 'ack_invalid' || failureType === 'connection_lost';
const retryAllowed = !acknowledgementFailure || delivery.retryEnabled !== false;
const finalFailure = !retryAllowed || retryCount >= downstreamMaxRetries();
const finalStatus = failureType === 'ack_rejected' ? 'rejected' : acknowledgementFailure ? 'unconfirmed' : 'failed';
@@ -1265,7 +1269,20 @@ export class SendChainService implements OnModuleInit, OnModuleDestroy {
};
await this.prisma.cmppDownstreamDelivery.update({
where: { id: delivery.id },
data: { status: 'pending', retryCount: 0, nextRetryAt: null, ackDeadlineAt: null, lastError: null },
data: {
status: 'pending',
retryCount: 0,
nextRetryAt: null,
sentAt: null,
acknowledgedAt: null,
ackDeadlineAt: null,
ackResult: null,
ackSequenceId: null,
ackMessageId: null,
connectionId: null,
deliveredAt: null,
lastError: null,
},
});
try {
const result = await this.postGatewayControl(path, requestPayload) as GatewayControlDeliveryResult;
@@ -1649,6 +1666,7 @@ export class SendChainService implements OnModuleInit, OnModuleDestroy {
unitPrice: billing.unitPrice,
amountCents: billing.amountCents,
queuePriority,
cmppSubmitSequenceId: data.sequenceId == null ? null : String(data.sequenceId),
status: 'validating',
},
});
@@ -2140,6 +2158,7 @@ export class SendChainService implements OnModuleInit, OnModuleDestroy {
applicationId?: string | null;
messageId: string;
phoneNumber: string;
cmppSubmitSequenceId?: string | null;
},
errorCode: string,
reason: string,
@@ -2181,6 +2200,7 @@ export class SendChainService implements OnModuleInit, OnModuleDestroy {
rawStatus: 'REJECTD',
errorCode,
errorMessage: reason,
submitSequenceId: message.cmppSubmitSequenceId ? Number(message.cmppSubmitSequenceId) : undefined,
deliveredAt: deliveredAt.toISOString(),
},
});