fix(firstleg): read concurrent customs initialization with current row lock

This commit is contained in:
2026-10-05 16:35:22 +08:00
parent 090f57bfb1
commit 261c720c77
3 changed files with 77 additions and 4 deletions
@@ -563,7 +563,12 @@ public class ContainerCustomsService {
if (!"COMPLETED".equals(plan.loadingPlanStatus())) throw conflict("装柜完成后才能处理报关资料");
boolean refund = rows.stream().anyMatch(row -> "TAX_REFUND".equals(row.taxMode()));
mapper.insertContainer(IdWorker.getId(), planId, plan.containerBookingId(), refund ? WAITING : READY);
return refresh(planId);
// A concurrent INSERT IGNORE may wait for another request's insert to commit. The
// transaction's earlier plan reads can retain an RR snapshot that cannot see that row.
// Read the winning aggregate under its row lock, rather than reusing a snapshot read.
ContainerRow container = mapper.lockContainer(planId);
if (container == null) throw conflict("整柜报关记录初始化失败");
return refresh(planId, container);
}
private ContainerRow ensureMutable(long planId) {
@@ -573,7 +578,10 @@ public class ContainerCustomsService {
}
private ContainerRow refresh(long planId) {
ContainerRow value = mapper.container(planId);
return refresh(planId, mapper.container(planId));
}
private ContainerRow refresh(long planId, ContainerRow value) {
if (value == null || !Set.of(WAITING, READY).contains(value.status())) return value;
String status = mapper.missingRefundCount(planId, value.id()) == 0 ? READY : WAITING;
if (!status.equals(value.status())) {