diff --git a/backend/services/trading-service/src/application/services/c2c.service.ts b/backend/services/trading-service/src/application/services/c2c.service.ts index 69852dc2..6d6da83b 100644 --- a/backend/services/trading-service/src/application/services/c2c.service.ts +++ b/backend/services/trading-service/src/application/services/c2c.service.ts @@ -785,7 +785,7 @@ export class C2cService { const priceDecimal = new Decimal(freshOrder.price); // 查找是否已有可合并的 PENDING 订单(同 maker + 同类型 + 同价格) - const existingPending = await tx.c2cOrder.findFirst({ + let existingPending = await tx.c2cOrder.findFirst({ where: { makerAccountSequence: freshOrder.makerAccountSequence, type: freshOrder.type as any, @@ -799,21 +799,35 @@ export class C2cService { const existingQty = new Decimal(existingPending.quantity.toString()); const mergedQty = existingQty.plus(quantityDecimal); const mergedTotal = priceDecimal.mul(mergedQty).toString(); - restoreOrderNo = existingPending.orderNo; this.logger.log( - `[EXPIRY][TX] 步骤3: 合并到已有 PENDING 订单 ${existingPending.orderNo}, ` + + `[EXPIRY][TX] 步骤3: 尝试合并到 PENDING 订单 ${existingPending.orderNo}, ` + `原数量=${existingQty} + 恢复=${quantityDecimal} = ${mergedQty}`, ); - await tx.c2cOrder.update({ - where: { orderNo: existingPending.orderNo }, + // 用 updateMany + status 条件防止竞态:如果订单在 findFirst 后被 takeOrder 接走,count=0 + const updateResult = await tx.c2cOrder.updateMany({ + where: { + orderNo: existingPending.orderNo, + status: C2C_ORDER_STATUS.PENDING as any, + }, data: { quantity: mergedQty.toString(), 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 订单 restoreOrderNo = this.generateOrderNo(); const totalAmount = priceDecimal.mul(quantityDecimal).toString();