fix(shadow): recover confirmed late evidence commits
This commit is contained in:
69
docs/runbooks/ft546-shadow-20260914-commit-recovery.md
Normal file
69
docs/runbooks/ft546-shadow-20260914-commit-recovery.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# FT546 影子程序:2026-09-14 证据提交超时修复
|
||||
|
||||
## 适用版本与范围
|
||||
|
||||
- 分支:`optimize/wcs`
|
||||
- 修复前源码:`0d53f41`
|
||||
- 新 buildId:`ft546-shadow-20260914-commit-recovery-v1`
|
||||
- 修改范围:`ruoyi-wcs-shadow`。正式 WCS 调度、PLC/WMS 通信及生产数据库不作改动。
|
||||
- 无 SQL 迁移,无需清空影子库或更换 IDEA 连接配置;仍按现场源码方式编译启动。
|
||||
|
||||
本版本用于恢复持续影子采集,不代表批准新调度算法接管正式设备。
|
||||
|
||||
## 故障证据
|
||||
|
||||
9 月 14 日检查的旧 runId 为 `10ec02d4-5a64-4ea9-bfc4-6f03eca5089c`。
|
||||
最后成功周期为北京时间 9 月 11 日 02:31:03.399,此后心跳继续更新,采集却保持停止。
|
||||
超时诊断记录周期 10001 ms,其中前置心跳 4782 ms、来源读取 48 ms、证据提交 5154 ms;
|
||||
工作线程当时位于 SQL Server JDBC 的提交/套接字读取路径。复查线程栈时,该工作线程已经空闲。
|
||||
|
||||
旧实现一旦超过周期看门狗预算,就取消 Future 并永久停采,即使原事务后来正常结束,也无法确认并恢复。
|
||||
现有证据不能确定数据库延迟由磁盘、锁、网络中的哪一项造成;本次修复不将这些推测当作已确认根因。
|
||||
|
||||
## 修复后的行为
|
||||
|
||||
1. 保留首次采集前的心跳检查。之后正常周期仅在完成后写一次心跳,减少证据库写入和前置耗时。
|
||||
2. 保留 10 秒周期预算。若超时发生在 `TRANSACTION_COMMIT` 或 `RECORDING`,保留原 Future,进入等待确认状态,不启动新批次、不重放旧事务,也不取消正在提交的 JDBC 调用。
|
||||
3. 后续调度检查原任务的终态。只有正常结束,包括事务清理及提交后回调完成,才确认迟到成功、推进原批次游标,并允许下一批采集;跨延迟区间的待比较数据会失效。
|
||||
4. 提交失败、确认丢失或等待期间心跳写入失败时仍停止采集。原任务持续未结束且等待超过 30 秒时,以 `SHADOW_COMMIT_COMPLETION_UNCONFIRMED` 停采。窗口按调度轮询检查,同时采用单调时间与墙上时间,避免时钟回拨导致无限等待。
|
||||
5. 超过等待窗口后,不再调度新批次,但原数据库事务仍可能随后提交。停止采集不等于已回滚,不能据此盲目重放原事务。
|
||||
6. 非提交阶段超时继续采用原有停止保护。人工关闭后,即使旧提交迟到完成,也不能将状态恢复为 READY。
|
||||
|
||||
仅影子证据 SQL Server 连接增加 `socketTimeout=15000` 毫秒及 `cancelQueryTimeout=1` 秒。
|
||||
现有语句超时 3 秒、连接池大小 2、连接获取等待 2 秒保持不变,来源只读连接配置保持不变。
|
||||
这些超时限制单次驱动等待,不保证整个周期或 JDBC 清理严格在 15 秒内返回。
|
||||
|
||||
## 如何判断是否仍在采集
|
||||
|
||||
在服务器浏览器打开 `http://127.0.0.1:18091/shadow/status`:
|
||||
|
||||
- 正常:`status=READY`、`collectionStopped=false`、`awaitingCommitCompletion=false`;重复查看时 `lastCompletedCycle` 应持续推进。
|
||||
- 等待迟到提交:`awaitingCommitCompletion=true`,原因 `SHADOW_COMMIT_AWAITING_COMPLETION`。此时不启动新采集。
|
||||
- 停止采集:`collectionStopped=true`。进程存活或心跳时间更新不能作为持续采集的依据。
|
||||
- `lastCollectionFailure` 保留证据事务异常及可提取的 SQLState 等诊断;恢复后历史失败记录仍可能存在,应结合当前状态与时间判断。
|
||||
|
||||
迟到成功时日志包含 `late commit confirmed`。永久停采后每分钟输出一次 `collection remains stopped` 提醒。
|
||||
|
||||
## 本地验证
|
||||
|
||||
- 完整回归:核心 131 项、协议 10 项、影子 221 项,共 362 项;360 项通过,2 项因缺少另一组历史归档输入跳过,0 失败、0 错误。
|
||||
- 当前 11 份及占用场景 50 份现场输入回放通过。
|
||||
- 完整回归后补充了重复诊断快照的计时测试,单独运行该测试类 3 项全部通过;该补充之后未修改生产代码。
|
||||
- 使用真实 H2 事务注入提交延迟,验证迟到成功只提交一次、随后新批次继续、失败/确认丢失不重放、等待超限保护、关闭后不复活及心跳失败保护。
|
||||
- 使用 SQL Server JDBC 9.2.1.jre8 的属性解析验证有效超时配置,包括 URL 中无限等待值被覆盖的情形;此项未连接实际 SQL Server。
|
||||
- Java 8 `1.8.0_152`、Maven `3.6.0`,离线执行影子模块及其依赖的 `clean compile`,结果 `BUILD SUCCESS`。
|
||||
- 独立代码核验未发现阻止交付的问题,`git diff --check` 通过。
|
||||
|
||||
本地事务故障注入不等同于真实 SQL Server 网络故障试验。长期数据库抖动下的表现仍需重新采集现场运行记录。
|
||||
|
||||
## 现场更新与启动核对
|
||||
|
||||
现场影子源码目录为 `C:\project\FT546-WCS-SHANDOW`。更新前重新核实该目录版本、影子主类及 18091 监听进程,
|
||||
只停止确认属于影子程序的旧进程。保留现场 `.gitignore`、IDEA 配置、`opencode.json` 与 `shadow-evidence`。
|
||||
|
||||
将影子分支快进到本次修复提交,使用现场 Java 8、Maven 3.6.0 及现有离线依赖库编译。
|
||||
核实新 buildId、Java class 主版本 52、正式 WCS/WMS 进程仍在运行,再由用户在 IDEA 启动 `Ft546ShadowApplication`。
|
||||
本说明描述更新流程,不单独证明现场已更新;以本次现场操作记录为准。
|
||||
|
||||
启动后确认新的 runId/buildId、全部启动检查 PASS,以及多个采集周期持续落库。
|
||||
后续上线评估按安全性、有效任务覆盖、载货运输及任务完成能力检查;新旧调度逐条一致不是验收门槛。
|
||||
Reference in New Issue
Block a user