fix: 使用领取令牌隔离日计划进度
This commit is contained in:
@@ -225,25 +225,23 @@ List<DailyPlanDO> selectSleevingCandidates();
|
||||
|
||||
- [ ] **步骤 2:实现受控写入**
|
||||
|
||||
XML 提供 `insertDailyPlan`、`updateNotStartedPlan`、`updateStateWithVersion`、`updateSortWithVersion`、`updateWeightWithVersion` 和两个原子进度方法。版本更新必须使用:
|
||||
XML 提供 `insertDailyPlan`、`updateNotStartedPlan`、`updateStateWithVersion`、`updateSortWithVersion`、`updateWeightWithVersion` 和两个基于 Claim 的原子进度方法。页面写操作使用日计划版本;调度进度以 Claim 令牌及领取时对应作业进度作为并发边界:
|
||||
|
||||
```sql
|
||||
UPDATE lms_daily_plan
|
||||
SET stocked_qty = stocked_qty + #{incrementQty},
|
||||
stocking_status = CASE
|
||||
WHEN stocked_qty + #{incrementQty} = plan_qty + append_qty THEN 2
|
||||
WHEN stocking_status = 1 AND stocked_qty + #{incrementQty} = plan_qty + append_qty THEN 2
|
||||
ELSE stocking_status
|
||||
END,
|
||||
version = version + 1,
|
||||
updater = #{updater}
|
||||
WHERE daily_plan_id = #{dailyPlanId}
|
||||
AND version = #{version}
|
||||
AND order_status = 1
|
||||
AND stocking_status = 1
|
||||
AND stocked_qty = #{claimProgressQty}
|
||||
AND stocked_qty + #{incrementQty} <= plan_qty + append_qty
|
||||
```
|
||||
|
||||
套管方法使用同样约束。受影响行数不是 1 时由 Service 区分版本冲突或数量超限。
|
||||
套管方法使用独立的 `sleeved_qty` 快照约束。排序、权重、ERP 追加和另一作业进度引起的日计划版本变化不影响确认。取消或结束只阻止新领取,已有有效 Claim 仍允许累计数量,且 SQL 不覆盖用户选择的取消或结束状态。受影响行数不是 1 时由 Service 区分进度冲突或数量超限。
|
||||
|
||||
- [ ] **步骤 3:实现策略与日志 Mapper**
|
||||
|
||||
@@ -359,7 +357,7 @@ POST /lms/daily-plan/erpPush
|
||||
|
||||
- [ ] **步骤 1:定义调度返回对象**
|
||||
|
||||
创建 `DailyPlanScheduleCandidate`,包含日计划 ID、计划编号、物料信息、建议处理数量、版本号和策略模式。
|
||||
创建 `DailyPlanScheduleCandidate`,包含日计划 ID、计划编号、物料信息、建议处理数量、版本号、策略模式、排他 Claim 令牌和租约过期时间。版本号仅供展示审计,不作为进度确认并发边界。
|
||||
|
||||
- [ ] **步骤 2:实现顺序模式选择**
|
||||
|
||||
@@ -367,18 +365,18 @@ POST /lms/daily-plan/erpPush
|
||||
|
||||
- [ ] **步骤 3:实现权重轮转选择**
|
||||
|
||||
根据策略游标从有序候选列表定位下一张;建议数量为 `min(weight, remainingQty)`。完成选择后以版本号更新游标到下一张计划。游标无效时从顺序第一张开始。
|
||||
根据策略游标从有序候选列表定位下一张;建议数量为 `min(weight, remainingQty)`。先原子创建 Claim,成功后再以策略版本号更新游标到下一张计划,两者同事务提交。游标无效时从顺序第一张开始。
|
||||
|
||||
- [ ] **步骤 4:实现原子进度更新**
|
||||
|
||||
提供:
|
||||
|
||||
```java
|
||||
void increaseStockedQuantity(Long dailyPlanId, Integer quantity, Integer version, String operator);
|
||||
void increaseSleevedQuantity(Long dailyPlanId, Integer quantity, Integer version, String operator);
|
||||
void increaseStockedQuantity(String claimToken, Long dailyPlanId, Integer quantity, String operator);
|
||||
void increaseSleevedQuantity(String claimToken, Long dailyPlanId, Integer quantity, String operator);
|
||||
```
|
||||
|
||||
更新到需求总量时同步写完成状态和完成时间,并追加操作日志。版本冲突或数量超限抛明确业务异常。
|
||||
确认先锁定并原子消费 Claim,再按 Claim 保存的对应作业进度快照更新数量并追加日志。备货、套管可独立并发;同一 Claim 重复确认幂等成功。更新到需求总量时,仅当该作业仍在进行中才同步写完成状态和完成时间;若用户已取消或结束则保留终态。另提供 Claim 续租、主动释放和过期回收能力。
|
||||
|
||||
- [ ] **步骤 5:编译并提交调度能力**
|
||||
|
||||
|
||||
@@ -221,11 +221,14 @@ ERP 推送不允许直接修改顺序、权重、当前完成数量或作业状
|
||||
|
||||
## 并发与事务
|
||||
|
||||
- 页面操作和定时器数量更新使用版本号进行乐观锁校验。
|
||||
- 页面状态及资料操作使用日计划版本号进行乐观锁校验;调度数量确认不绑定整张日计划版本。
|
||||
- 状态变更、数量变更和对应操作记录在同一事务中提交。
|
||||
- 批量调整顺序在一个事务内完成;任一计划版本冲突时整体回滚。
|
||||
- 策略切换和轮转游标更新使用版本号,避免两个调度线程重复选择同一轮计划。
|
||||
- 并发失败统一提示“日计划已发生变化,请刷新后重试”。
|
||||
- 每次调度先持久化排他 Claim,Claim 令牌、作业类型、预占数量、领取时作业进度和 Claim 自身版本共同构成确认并发边界。备货与套管 Claim 相互独立。
|
||||
- 进度确认先原子消费 Claim,再以领取时对应作业进度为条件累计数量;重复确认同一已完成 Claim 幂等成功,不重复计数。
|
||||
- 排序、权重、ERP 追加和另一作业进度不会阻断有效 Claim 确认。取消、结束后不再产生新 Claim,但已下发的有效 Claim 仍可确认;确认只累计数量,保留用户选择的取消或结束状态。
|
||||
- Claim 支持续租、主动释放和过期回收;过期或已释放 Claim 不得确认。
|
||||
|
||||
## 错误处理
|
||||
|
||||
|
||||
Reference in New Issue
Block a user