Files
FT546MWS/doc/algorithm-migration/README.md
2026-07-24 08:51:42 +08:00

198 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FT546 B 算法迁移与上线手册
## 1. 当前状态
`javaTest` 中验证过的 B 算法已经迁入 FT546MWS,Maven 模块名为
`fortucky-algorithm`。算法已经接入入库扫码、重新分配、项目出库、指定托盘出库、
WCS 作业完成回调和 PDA 整托出库确认。
当前生产默认模式为 `SHADOW`。在该模式下,B 算法会计算和记录结果,但原 WMS 流程仍
负责业务写入。只有完成本手册的实库诊断、影子比对和并发演练后,才允许切换到
`ACTIVE`。
算法没有修改 WCS 取任务规则、小车调度、提升机调度或同层批处理策略。它只决定货位、
库存和深位搬移步骤,执行仍走现有 `mydo_job` 和 WCS 回调。
## 2. 不可变业务规则
- 入库按密集通道由里到外分配。
- 出库按由外到里执行。
- 有待出库任务的通道禁止新入库。
- 指定深位托盘执行 `MOVE_OUT -> OUTBOUND -> RESTORE`。
- 移库缓存或楼层锁不足时返回 `WAITING`,不能拒绝任务,也不能绕回旧算法跳过约束。
- 只有入库确实没有任何合法货位时才允许拒绝。
- 项目出库只匹配项目号,默认整托出库。
- 深位工作流一次只创建下一条可执行 WMS 作业。
- WCS 出库完成后只到 `AT_EXIT`;PDA 整托确认成功后才开始恢复阻挡托盘。
## 3. 代码接入位置
| 位置 | 作用 |
|---|---|
| `fortucky-algorithm` | 纯 Java 入库、出库、理货算法,Repository、路由和应用服务 |
| `ToWmsServiceImpl.requestEnterByTaskNo` | 入库扫码规划和 ACTIVE 模式原子占位 |
| `ToWmsServiceImpl.reAssign` | 入库任务重新分配 |
| `OutStockoutServiceImpl.autoAllot` | 项目号和指定托盘出库规划 |
| `ToWmsServiceImpl.jobFinish` | WCS 移库/出库完成后推进深位工作流 |
| `PdaServiceImp.outMakeSure` | PDA 整托确认成功后创建首条恢复作业 |
| `PersistentOutboundWorkflowCoordinator` | LEGACY/SHADOW 隔离和 ACTIVE 工作流推进 |
| `OutboundWorkflowTransaction` | 工作流、货位锁、楼层锁和单条 WMS 作业的事务写入 |
## 4. 数据库对象说明
算法对象统一放在 `alg` 架构中。WMS 业务表仍在 `dbo`,算法安装脚本不会改变
`dbo.bas_stock`、`dbo.bas_cargo_space` 和 `dbo.mydo_job` 的字段结构。
| 对象 | 作用 |
|---|---|
| `alg.space_topology` | 货位到通道、深度和基础分区的拓扑映射 |
| `alg.inventory_item_snapshot` | 算法使用的库存明细快照 |
| `alg.space_inventory_summary` | 每个货位的库存、托盘、项目和产品汇总 |
| `alg.lane_state` | 通道占用、可用、待出库、断层和 `rowversion` |
| `alg.dirty_lane_queue` | 记录哪些通道发生变化,避免每次扫码全仓刷新 |
| `alg.reservation` | ACTIVE 模式入库货位预占 |
| `alg.deep_workflow_lock` | 同一仓库同一楼层的深位工作流互斥锁 |
| `alg.outbound_workflow` | 深位出库工作流头 |
| `alg.outbound_workflow_step` | MOVE_OUT、OUTBOUND、RESTORE 步骤及 WMS 作业关联 |
| `alg.outbound_workflow_space` | 工作流持有的源货位和移库缓存货位锁 |
| `alg.space_role` | 移库缓存、出库缓存、保护区等人工配置角色 |
| `alg.warehouse_policy` | 仓库级装载率和 FIFO 容差 |
| `alg.project_policy` | 项目隔离、公共项目和混放策略 |
| `alg.decision_log` | B 算法决策、等待/拒绝原因和输入版本审计 |
`alg.lane_state.state_version` 是 SQL Server `rowversion`。它只递增,不需要减小或
重置;数据库会自动维护,正常使用不需要担心字段耗尽。
## 5. 大仓库增量刷新
规划前,Java 只调用 `alg.usp_refresh_dirty_lanes`。存储过程先用短事务领取当前仓库的
脏通道并立即释放队列锁,再在独立事务中重建这些通道的库存快照、货位汇总和通道状态。
这样可以避免刷新过程与 WMS 业务表触发器形成相反的锁顺序。刷新期间新产生的变化会
保留在队列中;刷新失败时,已领取的通道会合并回队列,不会丢失变更。
以下变化会自动标记通道:
- `bas_stock` 库存新增、修改、移动和删除;
- `bas_cargo_space` 状态、锁、托盘号和结构变化;
- `mydo_job` 新建、状态变化、完成和删除;
- `alg.space_role` 缓存/保护角色变化;
- `alg.project_policy` 和 `alg.warehouse_policy` 策略变化。
普通库存、货位状态和作业变化不会重建全仓拓扑。只有新增/删除货位、换仓库、换通道、
列/排/层等结构变化才设置 `topology_dirty=1` 并重建该仓库拓扑。策略变更很少发生,
为了保证版本一致,会标记策略影响范围内的所有通道。
## 6. 部署步骤
### 6.1 维护窗口前准备
1. 备份 FT546 WMS 数据库。
2. 记录当前 WMS JAR、配置文件和数据库版本。
3. 确认每个启用深位出库的楼层至少配置 4 个 `RELOCATION_BUFFER`。
4. 清理或确认货位状态、货位托盘号和库存托盘号不一致的数据。
5. 确认不存在未处理的密集通道断层;存在断层的通道会保持不可入库。
### 6.2 安装数据库对象
连接 FT546 WMS 主库后执行:
1. `fortucky-algorithm/src/main/resources/db/sqlserver/install.sql`
2. `fortucky-algorithm/src/main/resources/db/sqlserver/diagnostics.sql`
推荐使用 SSMS 或 Azure Data Studio 执行,因为脚本使用 `GO` 分批。Navicat 可以连接、
查看和维护这些表;如果当前 Navicat 版本不能识别 `GO`,安装脚本改用 SSMS 执行,
不要手工删除 `GO` 后整段执行。
`install.sql` 首次安装会全量建立拓扑和快照。之后每次扫码只刷新脏通道。
### 6.3 部署 WMS
`application.yml` 已提供以下默认配置:
```yaml
fortucky:
algorithm:
mode: ${FORTUCKY_ALGORITHM_MODE:SHADOW}
warehouse-id: ${FORTUCKY_ALGORITHM_WAREHOUSE_ID:01}
page-size: ${FORTUCKY_ALGORITHM_PAGE_SIZE:100}
database-writes-enabled: ${FORTUCKY_ALGORITHM_DATABASE_WRITES_ENABLED:true}
legacy-fallback-on-technical-error: ${FORTUCKY_ALGORITHM_LEGACY_FALLBACK:false}
```
首次部署不要设置 `FORTUCKY_ALGORITHM_MODE=ACTIVE`。保持 `SHADOW`,打包并部署新的
`ruoyi-admin.jar`。
单据未带仓库号时,算法使用 `FORTUCKY_ALGORITHM_WAREHOUSE_ID`,入库、浅位出库和深位
工作流提交阶段都会复用同一个有效仓库号。算法 Repository 必须使用 WMS 注入的同一
`PlatformTransactionManager` 和主 `DataSource`;数据源不一致时应用启动失败,避免
预占与货位提交落在不同事务中。
## 7. SHADOW 验收
至少覆盖以下任务:
1. 空通道连续入库,检查货位是否由里到外。
2. 有待出库作业的通道再次入库,检查 B 算法是否排除该通道。
3. 项目号整托出库,检查是否从匹配项目的最外托盘开始。
4. 指定最外托盘出库,检查是否直接生成出库计划。
5. 指定深位托盘出库,检查计划是否为 `MOVE_OUT -> OUTBOUND -> RESTORE`。
6. 移库缓存不足或楼层已有深位流程,检查结果是否为 `WAITING`,任务仍保留。
7. 重复发送 WCS 完成回调和 PDA 确认,检查工作流不会重复推进。
8. 修改一个通道的库存,检查 `alg.dirty_lane_queue` 被消费,其他通道版本不变化。
在 Navicat 中重点查看:
```sql
SELECT TOP 100 * FROM alg.decision_log ORDER BY created_at DESC;
SELECT * FROM alg.dirty_lane_queue ORDER BY last_changed_at;
SELECT * FROM alg.outbound_workflow ORDER BY created_at DESC;
SELECT * FROM alg.outbound_workflow_step ORDER BY workflow_id, workflow_step;
SELECT * FROM alg.outbound_workflow_space WHERE status = 'ACTIVE';
SELECT * FROM alg.deep_workflow_lock WHERE status = 'ACTIVE';
```
只有满足以下条件才能切换 ACTIVE:
- `diagnostics.sql` 没有未解释的数据冲突;
- 所有启用楼层的移库缓存数量合格;
- SHADOW 中 B 方案结果符合业务规则;
- 并发入库不会重复占位;
- 重复 WCS/PDA 回调保持幂等;
- 深位流程可以完成全部恢复并释放货位锁和楼层锁;
- 已完成一轮数据库备份和回滚演练。
切换时设置环境变量 `FORTUCKY_ALGORITHM_MODE=ACTIVE` 并重启 WMS。建议先选一个仓库、
一个班次灰度,确认后再统一推广。
## 8. 回滚
业务异常时,先设置 `FORTUCKY_ALGORITHM_MODE=LEGACY` 并重启 WMS,让新任务立即回到旧
流程。不要在存在 `ACTIVE` 深位工作流时直接卸载数据库对象;先完成或人工处置工作流、
清空活动货位锁和楼层锁。
确认不再需要算法对象后,执行:
`fortucky-algorithm/src/main/resources/db/sqlserver/uninstall.sql`
该脚本只删除算法触发器和 `alg` 架构对象,不删除 WMS 业务库存、货位和作业数据。
## 9. 开发验证命令
在 FT546MWS 根目录执行:
```powershell
& 'D:\BDevTools\maven\apache-maven-3.9.11\bin\mvn.cmd' -pl fortucky-algorithm test
& 'D:\BDevTools\maven\apache-maven-3.9.11\bin\mvn.cmd' -pl ruoyi-admin -am test
& 'D:\BDevTools\maven\apache-maven-3.9.11\bin\mvn.cmd' test
& 'D:\BDevTools\maven\apache-maven-3.9.11\bin\mvn.cmd' package
```
本地 H2 测试覆盖算法、版本、增量刷新和工作流状态机。真实 SQL Server 的脚本安装、
触发器并发和存储过程事务仍必须在 FT546 测试库执行后才能批准 ACTIVE。
当前源码验证结果:`fortucky-algorithm` 117 项测试通过,WMS 接入测试 71 项通过,
`mvn test` 和 `mvn package` 均成功。生成的 `ruoyi-admin/target/ruoyi-admin.jar` 已确认
包含 `BOOT-INF/lib/fortucky-algorithm-3.9.0.jar`;本次产物 SHA-256 为
`8fe0816b86bba007b1070007a2bfb5ff51e7941587d0dbc811f7c69b59dca492`。这些是本地构建证据,
不替代真实 SQL Server 安装、触发器并发和存储过程回滚演练。