fix(cmpp): honor UTC inbox retry leases

This commit is contained in:
hectorzhao
2026-08-20 17:50:00 +08:00
parent 0b63bcd74e
commit 53073461e9
5 changed files with 44 additions and 6 deletions
@@ -336,6 +336,14 @@ function createPrismaMock() {
count: jest.fn().mockResolvedValue(0),
findFirst: jest.fn().mockResolvedValue(null),
},
smsApplicationDailyReservation: {
findUnique: jest.fn().mockResolvedValue(null),
create: jest.fn().mockResolvedValue({ id: 'daily-reservation-1' }),
},
phoneFrequencyReservation: {
findUnique: jest.fn().mockResolvedValue(null),
create: jest.fn().mockResolvedValue({ id: 'frequency-reservation-1' }),
},
smsBillingRecord: {
findFirst: jest.fn().mockResolvedValue(null),
create: jest.fn().mockResolvedValue({ id: 'bill-1' }),
@@ -2194,6 +2202,34 @@ describe('SendChainService', () => {
}
});
it('persists an idempotent daily quota reservation with a Prisma Date value', async () => {
const { service, prisma } = createService();
prisma.$queryRaw.mockResolvedValueOnce([{ tenantId: 'tenant-1', dailyLimit: 100000, usedCount: 1 }]);
await expect((service as any).tryReserveDailySendQuota('app-1', 1, 'workflow-1:daily-quota'))
.resolves.toEqual({ dailyLimit: 100000, usedCount: 1, reserved: true });
expect(prisma.smsApplicationDailyReservation.create).toHaveBeenCalledWith({
data: expect.objectContaining({
reservationKey: 'workflow-1:daily-quota',
usageDate: expect.any(Date),
}),
});
expect(prisma.smsApplicationDailyReservation.create.mock.calls[0][0].data.usageDate.toISOString())
.toMatch(/^\d{4}-\d{2}-\d{2}T00:00:00\.000Z$/);
});
it('claims Inbox leases against UTC for timestamp-without-time-zone columns', async () => {
const { service, prisma } = createService();
prisma.$queryRaw.mockResolvedValueOnce([]);
await (service as any).submission.inboundEntry.claimInboundWorkflows(5);
const sql = prisma.$queryRaw.mock.calls[0][0].strings.join(' ');
expect(sql).toContain("NOW() AT TIME ZONE 'UTC'");
expect(sql).toContain('FOR UPDATE SKIP LOCKED');
});
it('enqueues a freshly persisted inbound message without querying the task and message again', async () => {
const { service, prisma } = createService();
const add = jest.fn().mockResolvedValue(undefined);