feat(p3.2): bizType 方案B——常量换终值 svc-hall + 双值双查 + P1-02 行级绑定校验 + P1-03 R4 时序修复
build / build-push (push) Successful in 48s

- SvcFlowCallbackHandler.BIZ_TYPE → SvcBizTypes.CURRENT(svc-hall,H-1 实核 appKey=100008
  注册行 app_code);yml 回调白名单双值 [svc-hall, svc_item](收敛条件=另一类型不再可能
  产生事件,本轮不收敛;回滚也保双值)
- 双值双查补丁(先终值后存量,S0-H2 实测中心 svc_item 存量=0,次查为防御性兼容):
  ApplyViewGuard 办理人分支 / FlowReconcileJob 对账(命中判据=内容非空,兼容 miss 空载体)/
  progress 空态出参 / S2 审批代理 byBiz·todo(S2 已落)
- P1-02 行级事件绑定校验:事件 schId 与行一致、行有镜像实例时事件 instanceId 必须一致;
  不匹配 200 消费但不推进+告警日志(不抛 5xx 防重推风暴);行无值(首发回调早于回填)放行,
  doFlowApply 回填侧对实例不一致告警留痕(方案B 书面接受第二实例降级)
- P1-03 R4 时序修复:markResubmitted 清旧 flowResultJson(保留 lastInstanceVersion 跨轮
  乱序防护);Handler 终态守卫改版本感知(事件版本>已消费版本=新轮竞态窗口放行,不再以
  旧结果非空一刀切拒绝);非终态推进清残留 finishTime;三场景测试静态化注入
  (新轮回调先于 apply 响应/新轮快速终态/旧轮迟到重复)
- 测试断言按新语义更新:新件出站断言 svc-hall×3;全量 163/163 绿(Stage S3/P3.2)
This commit is contained in:
chenxing
2026-10-19 23:49:02 +08:00
parent ed3c9e6a72
commit 05d2143ce1
8 changed files with 179 additions and 35 deletions
@@ -4,7 +4,7 @@ import com.yunhai.svchall.entity.ServiceApply;
import com.yunhai.svchall.enums.ApplyFlowStatusEnum;
import com.yunhai.svchall.repository.ServiceApplyRepository;
import com.yunhai.svchall.service.FlowClient;
import com.yunhai.svchall.service.impl.SvcFlowCallbackHandler;
import com.yunhai.svchall.service.SvcBizTypes;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
@@ -55,8 +55,18 @@ public class FlowReconcileJob {
continue;
}
try {
Map<String, Object> remote = flowClient.getInstanceByBiz(
apply.getSchId(), SvcFlowCallbackHandler.BIZ_TYPE, String.valueOf(apply.getId()));
// 双值双查(P3.2 方案B):先终值后存量,首个命中实例为准——命中判据用内容
// (id/status 非空)而非"非 null",对 miss 形态(运行时 data=null / 空载体)都稳
Map<String, Object> remote = null;
for (String bizType : SvcBizTypes.queryOrder()) {
Map<String, Object> candidate = flowClient.getInstanceByBiz(
apply.getSchId(), bizType, String.valueOf(apply.getId()));
if (candidate != null
&& (candidate.get("id") != null || candidate.get("status") != null)) {
remote = candidate;
break;
}
}
if (remote == null) {
continue;
}