diff --git a/backend/services/planting-service/src/infrastructure/persistence/repositories/contract-signing-task.repository.impl.ts b/backend/services/planting-service/src/infrastructure/persistence/repositories/contract-signing-task.repository.impl.ts index 84f59741..095cd88b 100644 --- a/backend/services/planting-service/src/infrastructure/persistence/repositories/contract-signing-task.repository.impl.ts +++ b/backend/services/planting-service/src/infrastructure/persistence/repositories/contract-signing-task.repository.impl.ts @@ -42,53 +42,68 @@ export class ContractSigningTaskRepositoryImpl implements IContractSigningTaskRe }); return this.mapToDomain(updated); } else { - // 创建 - 使用 upsert 处理并发幂等性 - // 如果 orderNo 已存在,则只返回现有记录(不更新) - // 额外捕获 P2002 错误以处理极端并发情况 - try { - const result = await this.prisma.contractSigningTask.upsert({ + // 创建 - 使用重试机制处理并发幂等性 + // 先尝试查询,如果不存在再创建,如果创建失败(并发冲突)则重新查询 + const maxRetries = 3; + for (let attempt = 1; attempt <= maxRetries; attempt++) { + // 先检查是否已存在 + const existing = await this.prisma.contractSigningTask.findUnique({ where: { orderNo: task.orderNo }, - create: { - orderNo: task.orderNo, - userId: task.userId, - accountSequence: task.accountSequence, - templateId: task.templateId, - contractVersion: task.contractVersion, - contractContent: task.contractContent, - userPhoneNumber: task.userPhoneNumber, - userRealName: task.userRealName, - userIdCardNumber: task.userIdCardNumber, - treeCount: task.treeCount, - totalAmount: new Prisma.Decimal(task.totalAmount), - provinceCode: task.provinceCode, - provinceName: task.provinceName, - cityCode: task.cityCode, - cityName: task.cityName, - status: task.status, - expiresAt: task.expiresAt, - }, - // 如果已存在,不更新任何字段,只返回现有记录 - update: {}, }); - return this.mapToDomain(result); - } catch (error: unknown) { - // 处理并发创建时的唯一约束冲突 (Prisma P2002) - if ( - error && - typeof error === 'object' && - 'code' in error && - error.code === 'P2002' - ) { - // 记录已被其他并发请求创建,直接查询返回 - const existing = await this.prisma.contractSigningTask.findUnique({ - where: { orderNo: task.orderNo }, - }); - if (existing) { - return this.mapToDomain(existing); - } + if (existing) { + return this.mapToDomain(existing); + } + + try { + // 尝试创建 + const result = await this.prisma.contractSigningTask.create({ + data: { + orderNo: task.orderNo, + userId: task.userId, + accountSequence: task.accountSequence, + templateId: task.templateId, + contractVersion: task.contractVersion, + contractContent: task.contractContent, + userPhoneNumber: task.userPhoneNumber, + userRealName: task.userRealName, + userIdCardNumber: task.userIdCardNumber, + treeCount: task.treeCount, + totalAmount: new Prisma.Decimal(task.totalAmount), + provinceCode: task.provinceCode, + provinceName: task.provinceName, + cityCode: task.cityCode, + cityName: task.cityName, + status: task.status, + expiresAt: task.expiresAt, + }, + }); + return this.mapToDomain(result); + } catch (error: unknown) { + // 处理并发创建时的唯一约束冲突 (Prisma P2002) + if ( + error && + typeof error === 'object' && + 'code' in error && + error.code === 'P2002' + ) { + // 记录已被其他并发请求创建,等待一小段时间后重试查询 + if (attempt < maxRetries) { + await new Promise((resolve) => setTimeout(resolve, 50 * attempt)); + continue; + } + // 最后一次尝试查询 + const finalExisting = await this.prisma.contractSigningTask.findUnique({ + where: { orderNo: task.orderNo }, + }); + if (finalExisting) { + return this.mapToDomain(finalExisting); + } + } + throw error; } - throw error; } + // 不应该到达这里,但为了类型安全 + throw new Error(`Failed to create or find signing task after ${maxRetries} attempts`); } }