perf: remove paid result account lock contention
This commit is contained in:
@@ -11,7 +11,7 @@ function createPrismaMock() {
|
||||
findMany: jest.fn().mockResolvedValue([]),
|
||||
},
|
||||
tenantAccount: {
|
||||
findMany: jest.fn(),
|
||||
findMany: jest.fn().mockResolvedValue([]),
|
||||
findUnique: jest.fn().mockImplementation(() => Promise.resolve({ ...accountState })),
|
||||
findUniqueOrThrow: jest.fn().mockImplementation(() => Promise.resolve({ ...accountState })),
|
||||
create: jest.fn(),
|
||||
@@ -30,7 +30,7 @@ function createPrismaMock() {
|
||||
}),
|
||||
},
|
||||
accountTransaction: {
|
||||
findMany: jest.fn(),
|
||||
findMany: jest.fn().mockResolvedValue([]),
|
||||
findFirst: jest.fn(),
|
||||
findUnique: jest.fn().mockResolvedValue(null),
|
||||
findUniqueOrThrow: jest.fn().mockImplementation(({ where }) => Promise.resolve({ id: 'tx-charged', idempotencyKey: where.idempotencyKey })),
|
||||
@@ -55,6 +55,7 @@ function createPrismaMock() {
|
||||
create: jest.fn().mockResolvedValue({ id: 'operation-1' }),
|
||||
},
|
||||
$executeRaw: jest.fn(),
|
||||
$queryRaw: jest.fn(),
|
||||
};
|
||||
return Object.assign(prisma, {
|
||||
$transaction: jest.fn((callback: (client: typeof prisma) => unknown) => callback(prisma)),
|
||||
@@ -319,11 +320,11 @@ describe('BillingService', () => {
|
||||
it('settles a frozen SMS charge with one account lock and an idempotent ledger pair', async () => {
|
||||
const prisma = createPrismaMock();
|
||||
const rows = new Map<string, Record<string, unknown>>();
|
||||
prisma.accountTransaction.findUnique.mockImplementation(({ where }) => Promise.resolve(rows.get(where.idempotencyKey) ?? null));
|
||||
prisma.accountTransaction.findUniqueOrThrow.mockImplementation(({ where }) => Promise.resolve(rows.get(where.idempotencyKey)));
|
||||
prisma.accountTransaction.createMany.mockImplementation(({ data }) => {
|
||||
data.forEach((row: Record<string, unknown>) => rows.set(String(row.idempotencyKey), { id: `tx-${row.transactionType}`, ...row }));
|
||||
return Promise.resolve({ count: data.length });
|
||||
prisma.accountTransaction.findMany.mockImplementation(() => Promise.resolve([...rows.values()]));
|
||||
prisma.$queryRaw.mockImplementation(() => {
|
||||
const charged = { id: 'tx-charged', idempotencyKey: 'sms-charge:msg-paid-1', transactionType: 'charged', amountCents: -325 };
|
||||
rows.set(String(charged.idempotencyKey), charged);
|
||||
return Promise.resolve([charged]);
|
||||
});
|
||||
const service = new BillingService(prisma as never);
|
||||
const input = { tenantId: 'tenant-1', amountCents: 325, messageId: 'msg-paid-1', taskId: 'task-paid-1' };
|
||||
@@ -333,7 +334,8 @@ describe('BillingService', () => {
|
||||
|
||||
expect(first).toEqual(expect.objectContaining({ transactionType: 'charged', amountCents: -325 }));
|
||||
expect(replay).toEqual(first);
|
||||
expect(prisma.accountTransaction.createMany).toHaveBeenCalledTimes(1);
|
||||
expect(prisma.$queryRaw).toHaveBeenCalledTimes(1);
|
||||
expect(prisma.$executeRaw).not.toHaveBeenCalled();
|
||||
expect(prisma.tenantAccount.update).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user