fix(c2c): 用updateMany+status条件防止合并时的竞态条件
findFirst找到PENDING订单后,如果被takeOrder接走(状态变MATCHED), updateMany因status!=PENDING返回count=0,自动回退到创建新订单。 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
60d99add2c
commit
338321b3a2
|
|
@ -785,7 +785,7 @@ export class C2cService {
|
||||||
const priceDecimal = new Decimal(freshOrder.price);
|
const priceDecimal = new Decimal(freshOrder.price);
|
||||||
|
|
||||||
// 查找是否已有可合并的 PENDING 订单(同 maker + 同类型 + 同价格)
|
// 查找是否已有可合并的 PENDING 订单(同 maker + 同类型 + 同价格)
|
||||||
const existingPending = await tx.c2cOrder.findFirst({
|
let existingPending = await tx.c2cOrder.findFirst({
|
||||||
where: {
|
where: {
|
||||||
makerAccountSequence: freshOrder.makerAccountSequence,
|
makerAccountSequence: freshOrder.makerAccountSequence,
|
||||||
type: freshOrder.type as any,
|
type: freshOrder.type as any,
|
||||||
|
|
@ -799,21 +799,35 @@ export class C2cService {
|
||||||
const existingQty = new Decimal(existingPending.quantity.toString());
|
const existingQty = new Decimal(existingPending.quantity.toString());
|
||||||
const mergedQty = existingQty.plus(quantityDecimal);
|
const mergedQty = existingQty.plus(quantityDecimal);
|
||||||
const mergedTotal = priceDecimal.mul(mergedQty).toString();
|
const mergedTotal = priceDecimal.mul(mergedQty).toString();
|
||||||
restoreOrderNo = existingPending.orderNo;
|
|
||||||
|
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
`[EXPIRY][TX] 步骤3: 合并到已有 PENDING 订单 ${existingPending.orderNo}, ` +
|
`[EXPIRY][TX] 步骤3: 尝试合并到 PENDING 订单 ${existingPending.orderNo}, ` +
|
||||||
`原数量=${existingQty} + 恢复=${quantityDecimal} = ${mergedQty}`,
|
`原数量=${existingQty} + 恢复=${quantityDecimal} = ${mergedQty}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
await tx.c2cOrder.update({
|
// 用 updateMany + status 条件防止竞态:如果订单在 findFirst 后被 takeOrder 接走,count=0
|
||||||
where: { orderNo: existingPending.orderNo },
|
const updateResult = await tx.c2cOrder.updateMany({
|
||||||
|
where: {
|
||||||
|
orderNo: existingPending.orderNo,
|
||||||
|
status: C2C_ORDER_STATUS.PENDING as any,
|
||||||
|
},
|
||||||
data: {
|
data: {
|
||||||
quantity: mergedQty.toString(),
|
quantity: mergedQty.toString(),
|
||||||
totalAmount: mergedTotal,
|
totalAmount: mergedTotal,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
|
if (updateResult.count > 0) {
|
||||||
|
restoreOrderNo = existingPending.orderNo;
|
||||||
|
this.logger.log(`[EXPIRY][TX] 步骤3: 合并成功`);
|
||||||
|
} else {
|
||||||
|
// 订单已被接走(状态不再是 PENDING),回退到创建新订单
|
||||||
|
this.logger.warn(`[EXPIRY][TX] 步骤3: 订单 ${existingPending.orderNo} 已被接走,改为创建新订单`);
|
||||||
|
existingPending = null; // fall through to create
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldRestore && !restoreOrderNo) {
|
||||||
// 无可合并订单,创建新的 PENDING 订单
|
// 无可合并订单,创建新的 PENDING 订单
|
||||||
restoreOrderNo = this.generateOrderNo();
|
restoreOrderNo = this.generateOrderNo();
|
||||||
const totalAmount = priceDecimal.mul(quantityDecimal).toString();
|
const totalAmount = priceDecimal.mul(quantityDecimal).toString();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue