perf(cmpp): decouple supplier result callbacks

This commit is contained in:
hectorzhao
2026-08-20 14:19:42 +08:00
parent 485af688d2
commit 67b760a599
27 changed files with 1000 additions and 66 deletions
@@ -2216,6 +2216,46 @@ describe('SendChainService', () => {
});
});
it('treats a redelivered Outbox aggregate event as idempotent', async () => {
const { service, prisma, billing } = createService();
const baseSubmit = {
id: 'submit-1',
messageRecordId: 'record-1',
channelId: 'channel-1',
submitId: 'SUB-1',
submitStatus: 'accepted',
};
prisma.smsSubmitRecord.findUnique
.mockResolvedValueOnce({ ...baseSubmit, resultEventId: null })
.mockResolvedValueOnce({ ...baseSubmit, resultEventId: 'submit:SUB-1:aggregate' });
const event = {
eventId: 'submit:SUB-1:aggregate',
messageId: 'MSG-1',
channelId: 'channel-1',
submitId: 'SUB-1',
sequenceId: 7,
gatewayMessageId: 'GW-1',
submitStatus: 'accepted' as const,
submittedAt: '2026-07-01T10:00:00.000Z',
};
await service.handleSubmitResult(event);
await service.handleSubmitResult(event);
expect(billing.charge).toHaveBeenCalledTimes(1);
expect(billing.release).toHaveBeenCalledTimes(1);
expect(prisma.smsSubmitRecord.updateMany).toHaveBeenCalledWith({
where: {
id: 'submit-1',
OR: [{ resultEventId: null }, { resultEventId: 'submit:SUB-1:aggregate' }],
},
data: {
resultEventId: 'submit:SUB-1:aggregate',
resultProcessedAt: new Date('2026-07-01T10:00:00.000Z'),
},
});
});
it('rejects a legacy aggregate SubmitResult when it cannot match one submit attempt uniquely', async () => {
const { service, prisma } = createService();
prisma.smsSubmitRecord.findMany.mockResolvedValue([