test: add architecture and OpenAPI validation tooling

This commit is contained in:
2026-08-25 12:22:14 +08:00
parent 24df851acf
commit 0e0b6f8264
13 changed files with 544 additions and 17 deletions
@@ -4,8 +4,9 @@
本基线只分析 `firstleg` 同一部署单元,不拆微服务,不改变业务流程、数据库结构、OpenAPI 或跨服务契约。分析输入为:
- `src/main/java`:429 个 Java 文件;948 条可解析的模块内类依赖;66 个物理包。
- `src/test/java`:169 个 Java 文件。与主源码合并分析时共 598 个 Java 文件、1,635 条模块内类依赖、69 个物理包。
- 首切片实施前 `src/main/java`:429 个 Java 文件;948 条可解析的模块内类依赖;66 个物理包。
- 首切片实施前 `src/test/java`:169 个 Java 文件。与主源码合并分析时共 598 个 Java 文件、1,635 条模块内类依赖、69 个物理包。
- 首切片实施后 `src/main/java`:430 个 Java 文件;949 条可解析的模块内类依赖;67 个物理包。增加项仅为只读 Out Port。
可重复命令:
@@ -78,7 +79,7 @@ split-loading
| 订舱报关拖车 | `oceanbooking/`、`customs/`,全局 `TruckAppointment*`、`WarehouseSupplier*`、出仓门禁贡献者 | 68 | 25/13 | `CustomsRepository` 直接读取入库与装柜 Mapper;订舱 Repository 直接读取全局货柜 Entity |
| 出仓 | `outbound/dispatch/` 与全局 `OutboundDispatch*`、运输历史、海外卸柜回写 | 17 | 8/10 | 与装柜、订舱门禁双向;海外回写直接使用全局货柜 Mapper/Entity |
| 船节点 | `portschedule/` 中 `CarrierScheduleQuery/Node/Adapter/Attempt/Exception*` | 22 | 8/1 | 查询服务直接读取订舱、船期、货柜 Entity;节点 Outbox 直接使用入库 Outbox Mapper/Entity |
| 客户统计 | `customerstatistics/` | 4 | 1/0 | Java 依赖最低;唯一跨切片依赖为 Controller 调用 `FirstlegScopeGuard`。SQL 只读订舱、货柜和装柜表 |
| 客户统计 | `customerstatistics/adapter`、`customerstatistics/application` | 5 | 1/0 | 已完成首切片;唯一跨切片依赖为 Web Adapter 调用 `FirstlegScopeGuard`。SQL 只读订舱、货柜和装柜表 |
| 财务集成 | 全局 `InternalFinance*`、`FinanceFeeSource*`、`FinanceCostSnapshot*`、付款凭证/快照类 | 20 | 17/6 | 直接读取入库费、柜次费、装柜及共享 Outbox 的 Entity/Mapper;继续受财务总控冻结的业务口径约束 |
共享技术层当前有 36 类,包含应用启动/配置、Scope Guard、单据号、部分跨服务 Client 及无法安全归属的全局模型。跨服务适配器按 `client` 包独立标识,不能因逻辑切片归属而被迁入应用核心。
@@ -104,7 +105,7 @@ split-loading
选择 `customer-statistics`,不是因为预设,而是因为以下实际证据:
1. 仅 4 个生产类,已集中在单一顶层包;没有业务切片对其产生 Java 类型入向依赖。
1. 实施前仅 4 个生产类且已集中在单一顶层包;实施后为原 4 类加 1 个只读 Out Port,没有业务切片对其产生 Java 类型入向依赖。
2. 唯一跨切片 Java 依赖为 Web Controller 对共享 `FirstlegScopeGuard` 的调用,不涉及 Entity 或 Mapper 泄漏。
3. 不属于当前八节点 SCC,也没有跨服务 Feign/HTTP Client。
4. 现有调用面稳定:一个平台 GET 接口、一个 Admin API 消费者、两个后端测试。
@@ -138,7 +139,7 @@ application -> application.model + common-core
## 7. 精确迁移清单、调用方与测试
首切片实施时只迁移/新增以下文件:
首切片已按以下清单迁移/新增:
| 当前文件 | 目标/动作 |
|---|---|
@@ -170,7 +171,7 @@ application -> application.model + common-core
- `scripts/analyze-firstleg-dependencies.mjs`:生成 JSON/Markdown/DOT 和 Tarjan SCC。
- `src/test/resources/architecture/firstleg-slice-dependencies.json`:冻结当前切片边;历史边可减少,不可增加。
- `scripts/analyze-firstleg-dependencies.test.mjs`:验证基线无新增边,并锁定客户统计 4 类、唯一出向边、零入向边和不进入 SCC。
- `scripts/analyze-firstleg-dependencies.test.mjs`:验证基线无新增边,并锁定客户统计目标 5 类/目录、唯一出向边、零入向边、不进入 SCC 和 application 依赖禁令。
与其他架构专项的依赖:
@@ -182,8 +183,18 @@ application -> application.model + common-core
```powershell
node --test firstleg/scripts/analyze-firstleg-dependencies.test.mjs
node firstleg/scripts/analyze-firstleg-dependencies.mjs --source-set main --format markdown
mvn -pl firstleg -am test-compile
mvn -pl firstleg -am -Dtest=CustomerTransitStatisticsServiceTest,CustomerTransitStatisticsContractTest -Dsurefire.failIfNoSpecifiedTests=false test
```
当前只新增只读脚本、合同和报告,没有 Java 签名变化;前两条命令是本轮直接门禁。第三条用于首切片实际迁移后的 Maven 行为验证。
首切片已经发生 Java 包与依赖签名变化,三条命令均为直接门禁;另需执行 `mvn -pl firstleg -am test-compile` 覆盖全部测试源码调用点。
## 11. 首切片实施结果
- 四个旧包类已删除,没有转发兼容层;目标五层目录已由 Node 合同锁定。
- `CustomerTransitStatisticsReader.SummaryProjection` 只包含 `customerId`、`containerCount`、`totalTeu`、`unknownContainerCount`、`asOf`,不暴露 MyBatis、Entity 或其他切片类型。
- 依赖方向由 `application Service -> MyBatis Mapper` 改为 `application Service -> application Port <- persistence Mapper`。
- 主源码由 429 类/948 条内部依赖/66 包变为 430 类/949 条内部依赖/67 包;36 条切片间边、88 条模型泄漏、31 条 Mapper 泄漏及全局 `mapper <-> repository` SCC 均未增加。客户统计仍只有 `adapter.in.web -> FirstlegScopeGuard` 一条跨切片边,且没有入向边。
- 根 Mapper 扫描只把旧精确包替换为新精确包,没有扩大扫描范围或增加兼容 Bean。
- 验证结果:Node 合同 3/3;`test-compile` 成功;客户统计加根扫描定向测试 7/7;`mvn -pl firstleg -am test` 共 854 个测试,0 失败、0 错误、3 跳过,构建成功。
- 首次并发执行 `test-compile` 时,其他专项同时写入共享 `target/classes` 导致若干无关 class 文件瞬时缺失;源符号核对正常,独立重跑 `test-compile` 与完整测试均成功。