docs: 统一中间件定位与 JDBC 轮询主路径口径
Align README, architecture, design, config comments, and ingress docs with the upstream message-processing middleware model: external CIIMS write to CMINMSGS, JDBC poll as production ingress, HTTP /cminmsgs/send as compat. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+50
-18
@@ -1,9 +1,33 @@
|
||||
# msgexchange-v2 设计文档
|
||||
|
||||
> **系统角色**:机场 OMMS **上游报文处理中间件**——消费 CIIMS/AODB 等上游经共享 MySQL 信箱
|
||||
> (`CMINMSGS`)投递的 XML 报文,解析处理后维护 Redis 动态并向 Kafka / 出站信箱投递;
|
||||
> **非**报文源系统。生产主路径 = **JDBC 轮询**发现新信;HTTP `POST /cminmsgs/send` = compat 写路径。
|
||||
> 本文对应仓库当前实现,给出模块级设计语义与依据;架构总览见
|
||||
> [architecture.md](architecture.md),权威架构为 Plane **ACM2-3**,实施计划与逐项验收为
|
||||
> **ACM2-10(U01–U30)**。文中标注「TODO/未实装」的条目均为已知开放项,不属文档遗漏。
|
||||
|
||||
## 0. 系统边界速览
|
||||
|
||||
```
|
||||
上游(CIIMS/AODB…) ──外部写──▶ 共享 MySQL CMINMSGS(DATE_PROCESSED IS NULL)
|
||||
│ JDBC 轮询/重扫(InboxPoller,U05)
|
||||
▼
|
||||
自有 PG PROC_STATE(PENDING) ──▶ 主泵 FIFO 处理
|
||||
│
|
||||
┌───────────────┼───────────────┐
|
||||
▼ ▼ ▼
|
||||
Redis 动态 Kafka msg/schd COUTMSGS 出站
|
||||
(阶段 A 权威) (下游订阅) (他人读取发送)
|
||||
|
||||
(compat)POST /cminmsgs/send ──▶ insertRaw + PG 入队(手工/对拍,非主拓扑)
|
||||
```
|
||||
|
||||
- **中间件定位**:本系统位于 CIIMS 与下游消费者之间,负责**采集 → 解析 → 决策 → 投递**;
|
||||
报文原文由上游写入共享信箱,本系统只读(主路径)或 compat 写(辅助)。
|
||||
- **与 legacy 对齐**:legacy `MsgExchangeRunner` 同样以 1s 轮询 `CMINMSGS` 为处理入口;
|
||||
legacy HTTP 收报接口在 nextgen 中保留为 compat,不改变生产主拓扑。
|
||||
|
||||
## 1. 领域模型
|
||||
|
||||
### 1.1 状态机与错误分类
|
||||
@@ -65,8 +89,8 @@ ErrorClass(两侧共用):
|
||||
**存储边界(ACM2-12 定案)**:
|
||||
- **自有 PostgreSQL** = 上表全部(消息管道 + 调度 + 请求 + 21 类)。本地事务只在此库:
|
||||
处理侧「MSG_EVENT 插入 + PROC_STATE→SUCCEEDED」同事务;其余跨存储一律外部副作用。
|
||||
- **共享 MySQL(cdairport,他人系统)仅信箱 DML、不建表**:收报写 CMINMSGS、出站写
|
||||
COUTMSGS(他人读取发送)。见 §3.1/§3.2 的事务模型。
|
||||
- **共享 MySQL(cdairport,他人系统)仅信箱 DML、不建表**:上游外部写 CMINMSGS;
|
||||
本系统 JDBC 轮询读 + 处理回填;出站写 COUTMSGS(他人读取发送)。见 §3.1/§3.2 的事务模型。
|
||||
- **Redis**:航班动态 flightInfo + 快照 **SCHD_GEN(gen)**——Lua 内原子「覆盖+按代差删+
|
||||
版本推进」;重放幂等由 Lua 承接(协议重设计属 U09),`RefDataRepository` 为目标实现的
|
||||
过渡占位接口。
|
||||
@@ -77,14 +101,20 @@ ErrorClass(两侧共用):
|
||||
|
||||
## 3. 核心流程设计
|
||||
|
||||
### 3.1 流程 1:收报(`InboxService.accept`)
|
||||
### 3.1 流程 1:收报(JDBC 轮询 + HTTP compat)
|
||||
|
||||
收报 = 共享信箱外部写 + 自有 PG 入队(ACM2-12,跨库,非同一事务):
|
||||
1. `insertRaw`:共享 MySQL CMINMSGS 落信成功(返回其主键 CMINMSGS_ID)——「已持久化」
|
||||
语义即刻成立,响应可返回(与现役逐字对拍后固化,U16);
|
||||
2. `procState.insert(id)`:自有 PG 建 PENDING 行入队;本步失败 → 补偿(以共享库
|
||||
`DATE_PROCESSED IS NULL` 重扫补建,U05 批次实现);
|
||||
3. 不解析报文、接收层无唯一约束(I3)。`wakePump()` 为 TODO 空操作——泵 1s 轮询兜底。
|
||||
**主路径(生产/SIS 口径)**:上游经 CIIMS 等外部系统写入共享 MySQL `CMINMSGS`
|
||||
(`DATE_PROCESSED IS NULL`);本系统 `ingress` 经 **JDBC 轮询**发现新信(与 legacy
|
||||
`MsgExchangeRunner.getNewMsgsAfterId` 同语义,1s 节律),自有 PG 入队:
|
||||
|
||||
1. `pollNew()`(U05,`InboxPoller`):JDBC 查共享库 `CMINMSGS_ID > watermark 且
|
||||
DATE_PROCESSED IS NULL`(及/或 PG 无对应 PROC_STATE 的补偿重扫);
|
||||
2. `procState.insert(id)`:自有 PG 建 PENDING 行入队;本步失败 → 下轮重扫补建;
|
||||
3. 不解析报文、接收层无唯一约束(I3);`wakePump()` 为 TODO 空操作——主泵 1s 轮询兜底。
|
||||
|
||||
**compat 路径(现役 HTTP 写)**:`InboxService.accept`(`POST /cminmsgs/send`)=
|
||||
共享信箱 `insertRaw` + 自有 PG 入队(跨库,非同一事务);「已持久化」响应语义与现役
|
||||
对拍(U16)。用于手工注入/影子对拍,**非**上游报文到达的主拓扑。
|
||||
|
||||
### 3.2 流程 2:主泵 tick(`Pump.tick`)
|
||||
|
||||
@@ -92,8 +122,9 @@ ErrorClass(两侧共用):
|
||||
|
||||
1. `headQueued()` 取作业、`headUnfinished()` 取最小未完成 CMINMSGS_ID(**含 FAILED**,
|
||||
消息间严格保序:队头退避未到期即 sleep 至到期点,后方消息永不越队)。
|
||||
2. `jobBefore(job, head)`:head 为空或队头 FAILED 时作业先行——**当前为入队时间近似,
|
||||
与「统一 FIFO」注释存在已知偏离(U15 未实装)**;统一序号列定案后消除。
|
||||
2. `jobBefore(job, head)`:head 为空或队头 FAILED 时作业先行——**当前为 head-state 近似**
|
||||
(非入队时间排序),与「统一 FIFO」注释存在已知偏离(U15 未实装);ACM2-12 口径为
|
||||
作业窗口执行(队头空闲/退避窗口),不追求与消息统一全序(Checks ④)。
|
||||
3. 队头 FAILED 且退避未到期:`poisoned()` 判定(attempts≥maxAttempts 或滞留超
|
||||
head-deadline 10m)→ DEAD(EXHAUSTED) 毒丸升级(Pump 侧;投递侧同语义属 U13,未实装);
|
||||
**实现注**:headDeadline 判据以 `updatedAt` 为锚,而 updatedAt 与 nextAttemptAt 同一次 FAILED
|
||||
@@ -107,8 +138,9 @@ ErrorClass(两侧共用):
|
||||
其余 → `Handler.decide(redis.hgetAllFlightInfo(), msg)` →
|
||||
阶段 A:Redis 先写(I2 happens-before,TODO redisApply)→ 自有 PG 事务 2:
|
||||
MSG_EVENT 插入 + PROC_STATE→SUCCEEDED(同库原子,@Transactional);
|
||||
CMINMSGS 回填(DATE_PROCESSED/STATUS)为共享信箱**外部回填**:PG 提交后异步/补偿执行,
|
||||
失败重试+告警(最终一致,ACM2-12;回滚接管语义以回填成功为界,需 Runbook 演练确认)。
|
||||
CMINMSGS 回填(DATE_PROCESSED/STATUS)为共享信箱**外部回填**:目标态为 PG 提交后
|
||||
异步/补偿执行,失败重试+告警(最终一致,ACM2-12);**当前实现为同步内联占位**
|
||||
(`insertAll → backfillOnSuccess → SUCCEEDED`,无 `@Transactional`,U05 定案并改)。
|
||||
5. 异常边界(U08):`processOne` 内 try/catch → `ProcFailure.fail(INFRA)`(attempts+1、
|
||||
退避、达上限 DEAD);`InterruptedException` 恢复中断位后**上抛**;loop 仅 catch
|
||||
`Exception` 作最后防线,`Error` 任其终止进程(异常必可见)。
|
||||
@@ -168,7 +200,7 @@ staging(流式解析+整包校验,TODO 阶段2;未实装→FAILED(UNSUPPOR
|
||||
|
||||
| 不变量 | 语义 | 落点 | 状态 |
|
||||
|---|---|---|---|
|
||||
| I1 | 单写者严格 FIFO + HOL 阻塞 + 毒丸升级 | `headUnfinished`/`headUnsent` 队头语义、`poisoned()` | 实装(attempts 毒丸生效;head-deadline 判据不可达待修,见 §3.2 注;job 相对队头的全序属 U15) |
|
||||
| I1 | 单写者严格 FIFO + HOL 阻塞 + 毒丸升级 | `headUnfinished`/`headUnsent` 队头语义、`poisoned()` | 实装(attempts 毒丸生效;head-deadline 判据不可达待修,见 §3.2 注;job 为 head-state 近似 / 作业窗口属 U15) |
|
||||
| I2 | Redis 先写、后于事件创建(happens-before) | `processOne` 阶段 A 分支 | TODO redisApply(流程占位已留) |
|
||||
| I3 | identity 首绑幂等;接收层无唯一约束;SUCCEEDED 回填 | `Identity`/`tryBindIdentity`/`backfillOnSuccess` | 实装 |
|
||||
| I4 | 清场仅删 ES 成功集;按代差删 | `HistorySweepJob`/SNAPSHOT_REPLACE delFields | 门禁实装,ES 接线 TODO |
|
||||
@@ -220,11 +252,11 @@ ACM2-12)、`flyway.datasources.default.*`、`mailbox.shared-mysql.*`(共享
|
||||
|
||||
| 项 | 缺口 | 计划 |
|
||||
|---|---|---|
|
||||
| U05 | 自有 PG 数据层无实装(PROC_STATE/MSG_EVENT/PUMP_JOB/REQ_TRACK/REF_MASTER + 信箱适配层 CminmsgMailbox/OutboxMailbox);`@Transactional`/allopen 未引入 → 生产 DI 装配失败 | U05 批次(Micronaut Data JDBC on PG + allopen + 信箱外部副作用与补偿回归) |
|
||||
| U05 | 自有 PG 数据层无实装 + **InboxPoller(JDBC 轮询/重扫)** 未实装(当前仅 compat HTTP `InboxService.accept`);信箱适配层 CminmsgMailbox/OutboxMailbox;`@Transactional`/allopen 未引入 → 生产 DI 装配失败;`application-dev.yml` 仍残留 MySQL datasource URL 占位(stub 下 enabled=false 不建连,U05 清理) | U05 批次(Micronaut Data JDBC on PG + InboxPoller + allopen + 信箱外部副作用与补偿回归) |
|
||||
| U07/U26 | `autostart` 默认关=有意门禁,但生产无 fail-fast;双实例无运行期防护 | fail-fast 定案 + 租约/DB 锁拒启 |
|
||||
| U09 | gen→Redis 协议未重设计(Lua 内原子版本推进;崩溃窗口=「Lua 完成/PG SUCCEEDED 未写」) | Redis 内版本 CAS + 恢复协议 + 测试(ACM2-12) |
|
||||
| U13 | 投递侧无 createdAt/headDeadline 超时升级、无 DEAD 告警出口;处理侧 head-deadline 判据亦不可达(见 §3.2 注) | WP2 |
|
||||
| U15 | job 与队头消息无统一全序(入队时间近似)——ACM2-12 后改口径:作业窗口执行,不追求与消息全序 | 作业窗口语义定稿(ACM2-12 Checks ④) |
|
||||
| U15 | job 与队头消息无统一全序(**head-state 近似**,非入队时间)——ACM2-12 口径:作业窗口执行,不追求与消息全序 | 作业窗口语义定稿(ACM2-12 Checks ④) |
|
||||
| U16 | `/cminmsgs/send` 无 @Consumes/字符集(实测 text/plain 415)、无错误路径契约(@ControllerAdvice) | WP2(legacy 逐字对拍固化) |
|
||||
| U17 | Eureka 注册名仍取 `micronaut.application.name`(=msgexchange-nextgen);`msgx.service-name` 无运行时消费方 → 影子/切流前注册名与文档契约脱节 | `micronaut.application.name=${msgx.service-name}`(application.yml) |
|
||||
| U18 | DDL 缺口(随 PG 化收窄:REQ_TRACK.COUTMSGS_ID 已 BIGINT;时间列口径 U05 定) | U05 批次 |
|
||||
@@ -232,5 +264,5 @@ ACM2-12)、`flyway.datasources.default.*`、`mailbox.shared-mysql.*`(共享
|
||||
| U22–U24 | 载荷类型收敛、eventSeq 未接线、每报文全量读语义定案 | WP3 |
|
||||
| U25/U28/U30 | 一致性哨兵实装、README 安全节/入口、索引与杂项 | WP3/4 |
|
||||
| U27 | 专有材料(SIS md 703KB / XSD 版权头)治理决策 | WP4(ACL 核验先行) |
|
||||
| ACM2-11/12 | 存储边界(自有 PG + 共享信箱 + Redis 动态/gen + 阶段 B 缓做):迁移 SQL/配置/接口注释已按定案调整(V1.0.0 PG);信箱适配层、gen Lua、作业窗口语义、影子重设计未实装 | ACM2-12 Checks ①–⑥ |
|
||||
| ACM2-11 | 21 类静态主数据独立 PG 参考库(datasources.reference):Repository 接口已拆(RefDataRepository=gen-only / StaticRefRepository),表结构/迁移/SOURCE 审计/ReferenceService 同步与应答接线未实装 | 阶段 6(U05 批次后);生产 Oracle 仅可能性,触发条件见 ACM2-11 |
|
||||
| ACM2-12 | 存储边界(自有 PG + 共享信箱 + Redis 动态/gen + 阶段 B 缓做):迁移 SQL/配置/接口注释已按定案调整(V1.0.0 PG);信箱适配层、gen Lua、作业窗口语义、影子重设计未实装 | ACM2-12 Checks ①–⑥ |
|
||||
| ACM2-11 | **决策史(已被 ACM2-12 吸收)**:曾讨论 21 类静态独立 PG 参考库;定案为并入自有 PG `REF_MASTER`(见 ACM2-12),勿再按 `datasources.reference` 第二库规划 | 仅作决策脉络参考 |
|
||||
|
||||
Reference in New Issue
Block a user