perf: batch paid CMPP accounting and weighted routes

This commit is contained in:
hectorzhao
2026-08-21 10:25:40 +08:00
parent 0176aa6952
commit 487b5282a6
12 changed files with 219 additions and 40 deletions
+46 -1
View File
@@ -416,7 +416,7 @@ export class BillingService {
availableAmount,
balanceCents,
creditCents,
canSend: availableAmount > 0,
canSend: availableAmount >= requiredAmount,
};
}
@@ -436,6 +436,51 @@ export class BillingService {
});
}
async settleFrozenCharge(data: { tenantId: string; amountCents: number; messageId: string; taskId: string; remark?: string }) {
const amountCents = data.amountCents ?? 0;
if (amountCents <= 0) return null;
const releaseKey = `sms-charge-release:${data.messageId}`;
const chargeKey = `sms-charge:${data.messageId}`;
return this.prisma.$transaction(async (tx) => {
await tx.$executeRaw`SELECT pg_advisory_xact_lock(hashtextextended(${'tenant-account:' + data.tenantId}, 0))`;
const [release, charge] = await Promise.all([
tx.accountTransaction.findUnique({ where: { idempotencyKey: releaseKey } }),
tx.accountTransaction.findUnique({ where: { idempotencyKey: chargeKey } }),
]);
if (charge) return charge;
const account = await tx.tenantAccount.findUniqueOrThrow({ where: { tenantId: data.tenantId } });
const balance = moneyToNumber(account.balanceCents);
if (release) {
const updated = await tx.tenantAccount.update({
where: { tenantId: data.tenantId },
data: { balanceCents: { decrement: amountCents } },
});
return tx.accountTransaction.create({
data: {
tenantId: data.tenantId, transactionType: 'charged', idempotencyKey: chargeKey,
amountCents: -amountCents, balanceAfter: updated.balanceCents,
relatedType: 'sms_message_record', relatedId: data.messageId, remark: '提交成功扣费',
},
});
}
await tx.accountTransaction.createMany({
data: [
{
tenantId: data.tenantId, transactionType: 'released', idempotencyKey: releaseKey,
amountCents, balanceAfter: balance + amountCents,
relatedType: 'sms_batch_task', relatedId: data.taskId, remark: data.remark,
},
{
tenantId: data.tenantId, transactionType: 'charged', idempotencyKey: chargeKey,
amountCents: -amountCents, balanceAfter: balance,
relatedType: 'sms_message_record', relatedId: data.messageId, remark: '提交成功扣费',
},
],
});
return tx.accountTransaction.findUniqueOrThrow({ where: { idempotencyKey: chargeKey } });
}, { isolationLevel: Prisma.TransactionIsolationLevel.ReadCommitted });
}
release(data: BillingActionDto) {
return this.applyAccountDelta({
...data,