fix(planting-service): 添加 P2002 错误捕获处理并发创建冲突

PostgreSQL 的 upsert 在高并发下仍可能出现唯一约束错误,
添加 try-catch 捕获 P2002 错误,发生冲突时直接查询返回已存在的记录。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2025-12-25 00:56:53 -08:00
parent 68e269b602
commit e7f2d69def
1 changed files with 45 additions and 25 deletions

View File

@ -43,31 +43,51 @@ export class ContractSigningTaskRepositoryImpl implements IContractSigningTaskRe
} else { } else {
// 创建 - 使用 upsert 处理并发幂等性 // 创建 - 使用 upsert 处理并发幂等性
// 如果 orderNo 已存在,则只返回现有记录(不更新) // 如果 orderNo 已存在,则只返回现有记录(不更新)
const result = await this.prisma.contractSigningTask.upsert({ // 额外捕获 P2002 错误以处理极端并发情况
where: { orderNo: task.orderNo }, try {
create: { const result = await this.prisma.contractSigningTask.upsert({
orderNo: task.orderNo, where: { orderNo: task.orderNo },
userId: task.userId, create: {
accountSequence: task.accountSequence, orderNo: task.orderNo,
templateId: task.templateId, userId: task.userId,
contractVersion: task.contractVersion, accountSequence: task.accountSequence,
contractContent: task.contractContent, templateId: task.templateId,
userPhoneNumber: task.userPhoneNumber, contractVersion: task.contractVersion,
userRealName: task.userRealName, contractContent: task.contractContent,
userIdCardNumber: task.userIdCardNumber, userPhoneNumber: task.userPhoneNumber,
treeCount: task.treeCount, userRealName: task.userRealName,
totalAmount: new Prisma.Decimal(task.totalAmount), userIdCardNumber: task.userIdCardNumber,
provinceCode: task.provinceCode, treeCount: task.treeCount,
provinceName: task.provinceName, totalAmount: new Prisma.Decimal(task.totalAmount),
cityCode: task.cityCode, provinceCode: task.provinceCode,
cityName: task.cityName, provinceName: task.provinceName,
status: task.status, cityCode: task.cityCode,
expiresAt: task.expiresAt, cityName: task.cityName,
}, status: task.status,
// 如果已存在,不更新任何字段,只返回现有记录 expiresAt: task.expiresAt,
update: {}, },
}); // 如果已存在,不更新任何字段,只返回现有记录
return this.mapToDomain(result); 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);
}
}
throw error;
}
} }
} }