fix: coordinate SMS completion and improve operations diagnostics
CSS quality / css-quality (push) Has been cancelled

This commit is contained in:
hectorzhao
2026-09-16 18:27:29 +08:00
parent a0209f93bc
commit a350aca883
40 changed files with 2599 additions and 366 deletions
@@ -1,3 +1,4 @@
import { completionContext } from './completion-context';
import { BadRequestException, Logger, NotFoundException } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { createHash, randomUUID } from 'node:crypto';
@@ -217,20 +218,24 @@ export class SendDownstreamDeliveryService {
const cmppDeliveryAllowed = deliveryAllowed || data.allowBusinessRejectionCmppDelivery === true;
if (deliveryAllowed && data.queueHttpWebhook !== false) {
try {
await this.openApi?.queueWebhookEvent({
tenantId: data.tenantId,
applicationId: data.applicationId,
messageRecordId: data.messageRecordId,
messageId: data.messageId,
uplinkMessageId: typeof data.payload.uplinkMessageId === 'string' ? data.payload.uplinkMessageId : undefined,
eventType: data.deliveryType,
payload: data.payload,
});
await this.openApi?.queueWebhookEvent(
{
tenantId: data.tenantId,
applicationId: data.applicationId,
messageRecordId: data.messageRecordId,
messageId: data.messageId,
uplinkMessageId:
typeof data.payload.uplinkMessageId === 'string' ? data.payload.uplinkMessageId : undefined,
eventType: data.deliveryType,
payload: data.payload,
},
completionContext.getStore()?.tx,
);
} catch (error) {
this.logger.error(
`HTTP webhook queue failed for ${data.deliveryType}/${data.messageId ?? '-'}: ${error instanceof Error ? error.message : String(error)}`,
);
if (data.propagateHttpQueueError) throw error;
if (data.propagateHttpQueueError || completionContext.getStore()) throw error;
}
}
if (data.queueCmppDelivery === false) {
@@ -249,6 +254,34 @@ export class SendDownstreamDeliveryService {
: data.deliveryType === 'uplink' && typeof data.payload.uplinkMessageId === 'string'
? `uplink:${data.payload.uplinkMessageId}`
: null;
if (completionContext.getStore()) {
if (!dedupeKey) throw new Error('completion_notification_identity_missing');
await this.prisma.cmppDownstreamDelivery.createMany({
data: [
{
tenantId: data.tenantId,
applicationId: data.applicationId,
messageRecordId: data.messageRecordId,
messageId: data.messageId,
dedupeKey,
deliveryType: data.deliveryType,
payload,
retryEnabled:
cmppDeliveryAllowed &&
(data.deliveryType === 'uplink'
? application.downstreamUplinkRetryEnabled
: application.downstreamReceiptRetryEnabled),
status: cmppDeliveryAllowed ? 'pending' : 'abandoned',
lastError: cmppDeliveryAllowed ? null : '企业应用已停用,保留回执但不再向客户应用推送',
},
],
skipDuplicates: true,
});
const retained = await this.prisma.cmppDownstreamDelivery.findUniqueOrThrow({ where: { dedupeKey } });
if (retained.messageRecordId !== data.messageRecordId || retained.applicationId !== data.applicationId)
throw new Error('completion_notification_identity_mismatch');
return retained;
}
let delivery;
try {
delivery = await this.prisma.cmppDownstreamDelivery.create({