docs: 修复跨文档冲突与外部规范口径
不动代码、配置与迁移,只收敛文档口径。
- 登记两项外部冲突:Q13 日计划缺失可选字段(SIS §3.16 注释 4 要求删除本地值,
与现行"未携带字段保留"相反)、Q14 主/共享删除顺序与 EROR 回报义务
(SIS §1.6.1-1.d / §4.8);航班级"缺席不删"补 SIS §3.16 注释 1 依据。
- flight-state §3.3 补主/共享关联按 FLID 值比较的规则。
- message-lifecycle:§11 水位不变量与 §5.1 空洞老化自洽;删除过期的 updatedAt
判据,统一为 PROCESSING_STARTED_AT + 可注入 Clock;§5.1/§6 补 SIS 480 分钟
Expiry 与 legacy 1 天保留窗,作为 Q2/Q6/Q7 的取值参照。
- architecture/design:明细表口径统一为 8 张资源明细表 + FLIGHT_ROUTE_POINT;
Oracle 11g 断言收敛为待适配验证;配置键按 application.yml 实际名称加 msgx. 前缀。
- user-stories:Q2/Q6/Q11 补外部锚点并收窄 Q11 到重置周期 + SNDR 值域;
新增 Q13/Q14 并挂入 US-05/06/08 前置;五个独立事实改为引用 message-lifecycle §1。
- README/legacy:文档基线改为代码基线 eea1120 + git log 指引;补"外部协议冲突以
SIS 为准"的维护规则;修正 /all/flights 过滤措辞;术语统一为「回填意图」。
验证:文档间章节引用 0 缺失、markdown 0 断链、SIS 引用小节全部存在、
Q1–Q14 正文与 Q 表双向可解析、代码块配对正常。
This commit is contained in:
+2
-2
@@ -1,6 +1,6 @@
|
||||
# 设计文档入口
|
||||
|
||||
当前实现核对日期:2026-09-10(代码基线 99a0f5f;文档基线 328bbf8)。文档中的目标能力不等于已实现;测试通过不等于现场已发布。
|
||||
当前实现核对日期:2026-09-10(代码基线 `eea1120`)。文档哈希不在此行回填,以 `git log -- docs/` 为准。文档中的目标能力不等于已实现;测试通过不等于现场已发布。
|
||||
|
||||
| 文档 | 唯一职责 |
|
||||
|---|---|
|
||||
@@ -13,4 +13,4 @@
|
||||
| [legacy/decision-flight-state-history.md](legacy/decision-flight-state-history.md) | 已撤销方案的存档说明;现行规则仍以 `flight-state.md` 为准。 |
|
||||
| [SIS 规范](legacy/SIS_AODB_RMS-V0.1.md) / [XSD](legacy/unisysaodbsis.xsd) | 外部协议事实;即使在 legacy 目录仍是兼容依据。 |
|
||||
|
||||
维护规则:架构写约束,设计写机制,规范(`flight-state.md`、`message-lifecycle.md`)写唯一规则,故事写目标,Plane 跟踪工作。不要在多份文档复制阶段清单;同一规则只允许一处定义,其他文档引用章节号。
|
||||
维护规则:架构写约束,设计写机制,规范(`flight-state.md`、`message-lifecycle.md`)写唯一规则,故事写目标,Plane 跟踪工作。不要在多份文档复制阶段清单;同一规则只允许一处定义,其他文档引用章节号。外部协议事实([SIS 规范](legacy/SIS_AODB_RMS-V0.1.md)、[XSD](legacy/unisysaodbsis.xsd))与现行文档冲突时以 SIS 为准;legacy 行为基线只描述现役行为。
|
||||
|
||||
@@ -76,7 +76,7 @@ CIIMS / AODB 等上游
|
||||
## 5. 必须保持的约束
|
||||
|
||||
- **消息严格 FIFO**:队头失败并退避时,后续消息仍不能越过它。只有队头完成或按失败策略进入终态后,队列才继续推进。收报重扫和水位设计必须防止较小 ID 漏入队而被后续消息越过。
|
||||
- **动态状态单写者**:`FLIGHT_SCHD` 及明细表只由主泵单线程写入。事务内第一步对 `PIPELINE_LOCK` 单行 `SELECT ... FOR UPDATE` 互斥;该方案在 PG/Oracle 11g 均无需数据库扩展或额外 DBA 特权。不能通过增加实例或处理线程直接扩容。
|
||||
- **动态状态单写者**:`FLIGHT_SCHD` 及明细表只由主泵单线程写入。事务内第一步对 `PIPELINE_LOCK` 单行 `SELECT ... FOR UPDATE` 互斥;该方案不依赖数据库扩展或额外 DBA 特权;Oracle 11g 待适配时验证。不能通过增加实例或处理线程直接扩容。
|
||||
- **身份去重**:同一业务身份只能绑定一条有效处理记录,重复报文不应再次产生业务副作用。具体身份组成和重放规则见设计文档。
|
||||
- **快照可恢复**:快照以 `PROC_STATE` 成功终态判定重放;每次成功写入推进 `STATE_VERSION`;`OPERATION_DAY` 一经确定不可变(见 flight-state.md §2.1)。
|
||||
- **物理清除只发生在历史归档**:删除一律先标记(FDEL)或由生命周期清除;历史存储未接通时必须删 0 条(见 flight-state.md §6)。
|
||||
@@ -87,7 +87,7 @@ CIIMS / AODB 等上游
|
||||
|
||||
| 存储 | 承载内容 | 职责说明 |
|
||||
|---|---|---|
|
||||
| 自有 PostgreSQL | 单行锁 `PIPELINE_LOCK`、处理状态与回填事实 `PROC_STATE`、消费水位 `INBOX_CURSOR`、待发事件 `MSG_EVENT`、请求跟踪 `REQ_TRACK`、航班当前态 `FLIGHT_SCHD` + 9 张明细表、留痕 `SCHD_SNAP_LOG` | 本系统唯一业务数据库。消息处理、状态推进、处理终态、回填意图与待发事件在单事务内原子提交;本地事务只在此库。 |
|
||||
| 自有 PostgreSQL | 单行锁 `PIPELINE_LOCK`、处理状态与回填事实 `PROC_STATE`、消费水位 `INBOX_CURSOR`、待发事件 `MSG_EVENT`、请求跟踪 `REQ_TRACK`、航班当前态 `FLIGHT_SCHD` + 8 张资源明细表 + `FLIGHT_ROUTE_POINT`、留痕 `SCHD_SNAP_LOG` | 本系统唯一业务数据库。消息处理、状态推进、处理终态、回填意图与待发事件在单事务内原子提交;本地事务只在此库。 |
|
||||
| 共享 MySQL | `CMINMSGS` 入站信箱、`COUTMSGS` 出站信箱 | 外部系统所有。本系统仅执行约定的信箱读写与处理标记回填,不建表、不迁移 schema、不写历史表;由库方按 Q9 执行的清除与历史归档见 message-lifecycle.md §6。兼容 HTTP 入口可按既有契约写入入站信箱。 |
|
||||
|
||||
**不使用跨库事务。** PG 事务只能保证“处理结果与待发事件一起提交”,不能覆盖 MySQL 回填或 Kafka 发送等外部副作用。跨存储依靠幂等、重试和持久化补偿恢复;各中断位置的判定与恢复动作统一见 [message-lifecycle.md](message-lifecycle.md) §4,本文不重复。
|
||||
|
||||
+17
-16
@@ -21,7 +21,7 @@
|
||||
| `MSG_EVENT` | 等待投递的事件(outbox) | `EVENT_ID` 决定投递顺序;`TARGET` 区分 `KAFKA:msg` / `KAFKA:schd`;`PARTITION_KEY` 恒为 `FLID`;`EVENT_TYPE` 区分 UPSERT 与 TOMBSTONE。 |
|
||||
| `REQ_TRACK` | 上游请求及应答关联 | 保存请求类型、覆盖运营日、发送方、出站信箱 ID 与发送/完成时间;同类只允许一个开放请求。登记、超时与应答匹配尚未实现(§10)。 |
|
||||
| `REF_MASTER` | 静态参考数据(目标表) | `(RTYPE, RKEY)` 唯一;尚未建表,客户端与刷新流程见 user-stories.md US-13/US-14(US-14 两类映射的存储落点未定)。 |
|
||||
| `FLIGHT_SCHD` | 航班标量及单值异常字段 | `FLID` 主键;`OPERATION_DAY` 一经确定不可变;版本与最近消息 ID 用于追踪。变长资源集合存于 9 张明细表,规则见 [flight-state.md](flight-state.md) §2,不在此重复。 |
|
||||
| `FLIGHT_SCHD` | 航班标量及单值异常字段 | `FLID` 主键;`OPERATION_DAY` 一经确定不可变;版本与最近消息 ID 用于追踪。变长资源集合存于 8 张资源明细表与 `FLIGHT_ROUTE_POINT`,规则见 [flight-state.md](flight-state.md) §2,不在此重复。 |
|
||||
| `INBOX_CURSOR` | 共享信箱消费水位 `W` | 单行游标;只随新 ID 成功入队推进,遇空洞即停,空洞超期判定为永久([message-lifecycle.md](message-lifecycle.md) §5.1)。 |
|
||||
| `PROC_STATE_HST` | 终态处理记录的归档目标 | 尚未建表;不得改写为共享库历史表。 |
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
SNDR | TYPE | STYP | SEQN
|
||||
```
|
||||
|
||||
接收时只按信箱 ID 去重;解码后才首次绑定业务身份。重试保留原有绑定,不能把自己判为重复消息。身份被另一条记录占用时,当前消息转为 `SKIPPED`,记录 `duplicate-of:<id>`。是否加入日期边界取决于上游序号重置规则,默认关闭;上线后不能随意更换身份算法。
|
||||
接收时只按信箱 ID 去重;解码后才首次绑定业务身份。重试保留原有绑定,不能把自己判为重复消息。身份被另一条记录占用时,当前消息转为 `SKIPPED`,记录 `duplicate-of:<id>`。是否加入日期边界取决于上游序号重置周期,默认关闭(`SEQN` 的取值范围与回绕已由 `SIS_AODB_RMS-V0.1.md` §2.8.1 定义,重置周期见 Q11);上线后不能随意更换身份算法。
|
||||
|
||||
分派与落库由 `MessageProcessor` 统一协调:按 `MsgKind` 把已绑定身份的队头消息交给对应事务协调器(DNLD/RESP → `ScheduleProcessor`,ADFT → `AdftProcessor`,FLOP → `FlopProcessor`,FDEL → `FdelProcessor`,其余 → `FAILED(UNSUPPORTED)`)。这些 Processor 在 `PIPELINE_LOCK` 事务内读取当前完整态,调用纯领域决策逻辑得到下一完整态与待发事件,再统一落库并登记回填意图;它们不直接触碰 Kafka。处理终态与业务变更在同一事务边界提交(见 flight-state.md §4)。
|
||||
|
||||
@@ -45,7 +45,7 @@ SNDR | TYPE | STYP | SEQN
|
||||
|
||||
```text
|
||||
处理:PENDING / FAILED → SUCCEEDED(成功)
|
||||
→ SKIPPED(业务重复;忽略/无匹配分支见 US-04/US-06,尚未实现)
|
||||
→ SKIPPED(业务重复已实现;忽略/无匹配分支见 US-04/US-06,尚未实现)
|
||||
→ FAILED(等待退避重试)
|
||||
→ DEAD(MALFORMED / PROTOCOL / EXHAUSTED,均需人工处置)
|
||||
|
||||
@@ -71,7 +71,7 @@ SNDR | TYPE | STYP | SEQN
|
||||
|
||||
`InboxPoller` 默认每秒按 ID 升序、有限批次(`claim-batch`,默认 50)读取水位之后的信箱记录(`ID > W`,**不以处理标记为谓词**),在自有 PG 建立 `PENDING` 并把水位推进到连续上界;入队与水位推进在同一 PG 事务内提交,重复扫描幂等、中断后重扫补建。收报层不解析业务载荷,也不回填已处理标记。
|
||||
|
||||
水位 W 与扫描谓词的完整口径(连续上界、遇空洞即停、空洞老化)唯一见 [message-lifecycle.md](message-lifecycle.md) §5.1;水位不是已处理标记,其有效性以 Q2 的 ID 单调承诺为前提。空洞老化阈值取 `pipeline.max-commit-delay`。
|
||||
水位 W 与扫描谓词的完整口径(连续上界、遇空洞即停、空洞老化)唯一见 [message-lifecycle.md](message-lifecycle.md) §5.1;水位不是已处理标记,其有效性以 Q2 的 ID 单调承诺为前提。空洞老化阈值取 `msgx.pipeline.max-commit-delay`。
|
||||
|
||||
兼容 HTTP 入口执行“写入共享信箱 → PG 入队”。两步不在同一事务中:信箱成功而 PG 失败时,原文不能丢失,由轮询补建;客户端失败重试可能再次写信箱,业务身份去重仍然必需。
|
||||
|
||||
@@ -94,7 +94,7 @@ SNDR | TYPE | STYP | SEQN
|
||||
DNLD / RESP → ScheduleProcessor(快照事务)
|
||||
ADFT / FLOP / FDEL → Adft / Flop / FdelProcessor(单航班事务)
|
||||
Unsupported → FAILED(UNSUPPORTED)
|
||||
PG 单事务:锁 + 航班变更 + 待发事件 + 终态 + 回填待办预登记
|
||||
PG 单事务:锁 + 航班变更 + 待发事件 + 终态 + 回填意图预登记
|
||||
→ 提交后回填信箱;失败由补偿待办重试
|
||||
```
|
||||
|
||||
@@ -112,7 +112,7 @@ SNDR | TYPE | STYP | SEQN
|
||||
1. **重放判定**:`PROC_STATE` 已存在成功终态 → 幂等成功,仅追加留痕,不重复写入。
|
||||
2. **整包校验**:声明记录数、航班标识与运营日推导等校验失败 → 整包 `DEAD(PROTOCOL)`,不写半包,既有状态保持不变。
|
||||
3. **事务写入**:锁内按 `FLID` 点查归属日,发现同一航班跨运营日即整包回滚并 `DEAD(PROTOCOL)`;通过后合并写主表与资源明细。报文未携带的航班不因本次日计划报文被删除。
|
||||
4. **提交结果**:同一事务保存 `KAFKA:schd` / `KAFKA:msg` 事件、置消息 `SUCCEEDED` 并预登记回填待办;事务提交后执行信箱回填,留痕在事务外追加。
|
||||
4. **提交结果**:同一事务保存 `KAFKA:schd` / `KAFKA:msg` 事件、置消息 `SUCCEEDED` 并预登记回填意图;事务提交后执行信箱回填,留痕在事务外追加。
|
||||
|
||||
单事务保证未提交变更整体回滚。消息重放由 `PROC_STATE` 的消息 ID 与业务身份控制;版本号不能单独证明消息身份。
|
||||
|
||||
@@ -133,7 +133,7 @@ REGISTERED → SENT → WAITING → DONE
|
||||
- 应答优先按已确认的回显字段精确匹配;回显契约未确认时的降级匹配(同类开放请求且 `DTTM ≥ sentAt`)存在跨代误配风险,必须明确接受并审计,不能宣称精确关联。比较前统一时区和时间单位。
|
||||
- 参考应答写入自有 `REF_MASTER`(尚未建表),日计划应答走快照流程;请求完成必须在相应数据处理成功之后,超时和迟到应答不能修改已关闭请求对应的状态。
|
||||
|
||||
请求与参考数据的交付范围见 user-stories.md US-08/US-13/US-14 与 §10。
|
||||
请求与参考数据的交付范围见 user-stories.md US-08/US-13/US-14 与本文 §10。
|
||||
|
||||
## 5. 事件投递
|
||||
|
||||
@@ -167,7 +167,7 @@ REGISTERED → SENT → WAITING → DONE
|
||||
|
||||
### 6.2 历史清理与归档
|
||||
|
||||
**航班历史清理**(`HistorySweepJob`,每天 03:30 触发):按 `HistoryProps` 的保留期与终态/静默判据选出候选(含 `DELETED`),先写历史存储,成功后物理删除主行与明细;历史存储未接通或 `history-store-enabled=false` 时删除 0 条。未经 FDEL、由生命周期直接清除的航班,清除前补发一次删除事件。语义与红线见 flight-state.md §6,不在此重复。
|
||||
**航班历史清理**(`HistorySweepJob`,每天 03:30 触发):按 `HistoryProps` 的保留期与终态/静默判据选出候选(含 `DELETED`),先写历史存储,成功后物理删除主行与明细;历史存储未接通或 `msgx.history.history-store-enabled=false` 时删除 0 条。未经 FDEL、由生命周期直接清除的航班,清除前补发一次删除事件。语义与红线见 flight-state.md §6,不在此重复。
|
||||
|
||||
**留痕清理**:`SCHD_SNAP_LOG` 保留 90 天,在历史清理窗口内按 `(SCOPE_END, RECV_AT)` 删除。
|
||||
|
||||
@@ -179,15 +179,16 @@ REGISTERED → SENT → WAITING → DONE
|
||||
|
||||
兼容入口为 `POST /cminmsgs/send`,请求体为原始 XML,当前成功响应为 HTTP 200、`text/plain` 格式的信箱记录 ID。这只表示接收结果,不表示业务处理成功。请求媒体类型、字符集和失败响应仍需与现役逐项对拍;查询与其他兼容端点不能因列入需求就视为已提供。
|
||||
|
||||
运行配置以 `application.yml`、`application-dev.yml` 和 `.env.example` 为准,设计上重点区分:
|
||||
运行配置以 `application.yml`、`application-dev.yml` 和 `.env.example` 为准,设计上重点区分(下列 `msgx.*` 参数以 `msgx.` 为前缀,`mailbox.*` 不带前缀):
|
||||
|
||||
- `pipeline.autostart` 与 `msgx.stubs`:分别控制管道启动与内存适配器;生产禁止 stub,默认不自动启动。
|
||||
- `pipeline.poll-interval / claim-batch / max-attempts / backoff / head-deadline`:控制轮询节奏、批次、重试上限、退避与队头滞留;这些参数不能改变 FIFO。
|
||||
- `pipeline.max-commit-delay / overdue-backfill / backfill-batch`:空洞老化阈值(Q2 最大提交时延)、超期补写期限 R(Q6)与回填扫描批量;R 与老化阈值都不能为提速而下调。
|
||||
- `msgx.pipeline.autostart` 与 `msgx.stubs`:分别控制管道启动与内存适配器;生产禁止 stub,默认不自动启动。
|
||||
- `msgx.pipeline.poll-interval / claim-batch / max-attempts / backoff-ms / backoff-cap-ms / head-deadline`:控制轮询节奏、批次、重试上限、退避与队头滞留;这些参数不能改变 FIFO。
|
||||
- `msgx.pipeline.max-commit-delay / overdue-backfill / backfill-batch`:空洞老化阈值(Q2 最大提交时延)、超期补写期限 R(Q6)与回填扫描批量;R 与老化阈值都不能为提速而下调。
|
||||
- `msgx.operation-day.zone / cutoff-hour`:运营日时区与切日边界,决定 `OPERATION_DAY` 推导(flight-state.md §2.1)。
|
||||
- `mailbox.processed-value`:写回共享信箱的处理标记值,仅限库方认可的 legacy 值集(Q7)。
|
||||
- `schd.flush-period / flush-limit`:控制状态通知的聚合延迟与批量大小。
|
||||
- `identity.include-day-boundary`:影响去重语义,不能作为普通调优项切换。
|
||||
- `mailbox.shared-mysql.enabled` 与 `history.history-store-enabled`:分别门控真实信箱与历史存储接线,默认关闭。
|
||||
- `msgx.schd.flush-period / flush-limit`:控制状态通知的聚合延迟与批量大小。
|
||||
- `msgx.identity.include-day-boundary`:影响去重语义,不能作为普通调优项切换;序号重置周期见 Q11。
|
||||
- `mailbox.shared-mysql.enabled` 与 `msgx.history.history-store-enabled`:分别门控真实信箱与历史存储接线,默认关闭。
|
||||
|
||||
日志关联消息 ID、事件 ID 和批次;失败记录错误分类、次数、下次执行时间。健康检查反映依赖实际可用性;队头滞留、积压、死信和补偿失败需要指标及告警。日志出口故障不得阻塞业务线程。
|
||||
|
||||
@@ -227,7 +228,7 @@ REGISTERED → SENT → WAITING → DONE
|
||||
|
||||
以下缺口直接影响上述设计是否成立,不能以类或接口已存在作为完成依据:
|
||||
|
||||
- **事务与外部副作用**:状态、事件、处理终态与回填意图同 PG 事务提交;回填意图落在 `PROC_STATE`(`BACKFILL_AT/NEXT_AT/ATTEMPTS/ERROR`),`BACKFILL_TODO` 已随 V2 迁移下线,[message-lifecycle.md](message-lifecycle.md) §4 的两个崩溃窗口(提交后回填前崩溃、待办二次落账失败)不再存在。回填本身仍是跨库单写,失败按退避重试并由超期期限 R 兜底;R 的取值待 Q6 确认。
|
||||
- **事务与外部副作用**:状态、事件、处理终态与回填意图同 PG 事务提交;回填意图落在 `PROC_STATE`(`BACKFILL_AT/NEXT_AT/ATTEMPTS/ERROR`),`BACKFILL_TODO` 已随 V2 迁移下线,[message-lifecycle.md](message-lifecycle.md) §4 的两个崩溃窗口(提交后回填前崩溃、回填意图二次落账失败)不再存在。回填本身仍是跨库单写,失败按退避重试并由超期期限 R 兜底;R 的取值待 Q6 确认。
|
||||
- **收报与调度**:水位 W 落库并与入队同事务推进,遇空洞即停、空洞超过 `max-commit-delay` 判定为永久(Q2 未书面确认前该阈值是假定值);旧空洞补齐后出现的新空洞会重置老化起点。较小 ID 迟提交与空洞场景的端到端顺序保证仍待与库方联合验证。HOL deadline 已改用 `PROCESSING_STARTED_AT` 和可注入 `Clock`;Q6 仍需确认长期积压与人工重放的期限口径。
|
||||
- **快照与业务能力**:DNLD/RESP/ADFT 与 FLOP/FDEL 处理器、整包校验与跨运营日整包拒绝均已接入;但 RESP 应答守卫与出站请求未实现,忽略规则(US-04)未实现,29 类 FLOP 与参考应答的逐类矩阵未补全,ADFT 缺失字段与 `FLID` 重用语义待上游确认。
|
||||
- **航班读写**:唯一写入口与权威读已落地;ROUT/ERUT 联合主键、空值/未知属性保真、事件在事务内只算一次、逐航班多次查询仍待修正(见 flight-state.md §6)。`/all/flights` 尚未实现。
|
||||
|
||||
+11
-5
@@ -9,7 +9,7 @@
|
||||
- `FLID` 是航班实例的唯一标识;不得由航班号、日期或资源号推断身份。
|
||||
- `FLIGHT_SCHD` 及其明细表是唯一权威当前态;展示视图只读,不能作为写入或对账来源。
|
||||
- 单活动主泵按信箱 FIFO 推进。事务内 `PIPELINE_LOCK` 只串行化本地状态提交,不替代选主或消息认领。
|
||||
- 状态写入、outbox 事件、处理终态和回填待办在同一 PostgreSQL 事务中提交;回填与 Kafka 投递在提交后独立重试。
|
||||
- 状态写入、outbox 事件、处理终态和回填意图在同一 PostgreSQL 事务中提交;回填与 Kafka 投递在提交后独立重试。
|
||||
|
||||
现场目标库为 Oracle 11g;当前已验证的实现基准是 PostgreSQL。Oracle 适配未完成前,不能把它视为可切换的运行时选项。
|
||||
|
||||
@@ -46,10 +46,12 @@
|
||||
|
||||
### 3.1 SCHD 日计划
|
||||
|
||||
SCHD DNLD/RESP 在整包校验通过后,逐条将报文携带的航班写入当前态。日计划只更新或创建其携带的 `FLID`,**不会因其他航班未出现在本次报文中而删除任何记录**。
|
||||
SCHD DNLD/RESP 在整包校验通过后,逐条将报文携带的航班写入当前态。日计划只更新或创建其携带的 `FLID`,**不会因其他航班未出现在本次报文中而删除任何记录**;SIS 同向(§3.16 注释 1 要求子系统自行保留前一日延误航班)。
|
||||
|
||||
日计划在重叠字段上可以覆盖当前动态值;未携带的字段按合并规则保留,显式清空才清除。每个成功写入的航班推进 `STATE_VERSION`,并在同一事务登记 `KAFKA:schd` 与 `KAFKA:msg` 事件。
|
||||
|
||||
**字段缺失语义与外部规范冲突**:SIS 规定最新日计划中未发送的可选字段表示 AODB 已无该数据、子系统应删除本地已有值(`SIS_AODB_RMS-V0.1.md` §3.16 注释 4;RESP 与 DNLD 同格式,见 §3.17),并要求以 AODB 最新数据覆盖本地(SIS §1.6.2)。这与上面的"未携带字段保留"相反。确认前两条并存,按 Q13 跟踪,不得据本节推定已与上游对齐。
|
||||
|
||||
消息重放由 `PROC_STATE` 的消息 ID 与 `identity_key` 控制;已成功提交的消息不得再次写入或重复登记事件。整包校验失败或运营日冲突时,整包不落地。
|
||||
|
||||
DNLD、RESP 和 ADFT 均已有路由入口。RESP 的请求匹配闭环、出站请求与超时重发仍是待交付项;未注册处理器不能被视为已实现。
|
||||
@@ -68,7 +70,9 @@ FDEL 是业务删除入口:仅在 `ACTIVE → DELETED` 时推进版本、保
|
||||
|
||||
ADFT 的字段缺失语义尚待上游确认。在确认前采用保守的 Set-only 规则:出现字段可更新,缺失字段不清空;不得把它当成日计划或动态全量替换。新建 ADFT 若带可解析的 `SODT`,按同一运营日规则计算 `OPERATION_DAY`;否则保留为 `NULL`。
|
||||
|
||||
主/共享航班级联:删除共享航班时更新主航班 `MAFL` 并向主航班通知;删除主航班时级联删除其子共享关联并发出删除通知;主/共享关系必须一次原子变更,不出现主已删、子残留的半状态。共享航班增量通常只更新并通知主航班,不直接发共享通知。这些语义同样约束 FDEL 之外的生命周期清理。
|
||||
主/共享航班级联:删除共享航班时更新主航班 `MAFL` 并向主航班通知;删除主航班时级联删除其子共享关联并发出删除通知;主/共享关系必须一次原子变更,不出现主已删、子残留的半状态。共享航班增量通常只更新并通知主航班,不直接发共享通知。这些语义同样约束 FDEL 之外的生命周期清理。主/共享关联的增删按 `FLID` 做值比较,不使用引用比较。
|
||||
|
||||
SIS 规定删除主航班时必须先删子共享航班、再删主航班,顺序不符时 RMS 应向 AODB 回发 EROR(`SIS_AODB_RMS-V0.1.md` §1.6.1-1.d,事件定义见 SIS §4.8)。本文的原子级联不发该回报,两者取舍见 Q14。
|
||||
|
||||
## 4. 处理事务与失败规则
|
||||
|
||||
@@ -76,7 +80,7 @@ ADFT 的字段缺失语义尚待上游确认。在确认前采用保守的 Set-o
|
||||
|
||||
1. 主泵只处理 FIFO 队头,解码并绑定业务身份。
|
||||
2. 校验消息结构、声明数量、航班标识和运营日;协议错误标记 `DEAD`,不提交半包。
|
||||
3. 在一个事务中取得 `PIPELINE_LOCK`,读取当前完整态,计算下一状态,写主表和明细表,登记 outbox 和回填待办。
|
||||
3. 在一个事务中取得 `PIPELINE_LOCK`,读取当前完整态,计算下一状态,写主表和明细表,登记 outbox 和回填意图。
|
||||
4. 同一事务提交处理终态;任一步失败则整体回滚并按错误类别重试或终止。
|
||||
5. 提交后回填共享信箱并异步投递 outbox;后续失败不得把已提交的 `SUCCEEDED` 改回失败。
|
||||
|
||||
@@ -99,6 +103,8 @@ ADFT 的字段缺失语义尚待上游确认。在确认前采用保守的 Set-o
|
||||
- Oracle 11g 的完整方言与集成验证;
|
||||
- RESP 请求—应答匹配和出站请求重发;
|
||||
- ADFT 缺失字段和 `FLID` 重用的上游语义;
|
||||
- 日计划缺失可选字段的删除语义(与 SIS 的冲突见 §3.1,Q13);
|
||||
- 主/共享删除顺序与 EROR 回报义务(Q14);
|
||||
- 未归属 `OPERATION_DAY` 航班的终止与保留策略;
|
||||
- ROUT/ERUT 联合主键迁移;
|
||||
- 批量一致性读取,以及动态事件仅在事务内计算一次的收敛。
|
||||
@@ -109,6 +115,6 @@ ADFT 的字段缺失语义尚待上游确认。在确认前采用保守的 Set-o
|
||||
- 同一时刻只有一个主泵推进 FIFO 状态;状态、事件、终态和回填意图原子提交。
|
||||
- 每个航班每次成功状态写入单调推进 `STATE_VERSION`;重复消息不重复推进。
|
||||
- `FLID` 唯一,已确定的 `OPERATION_DAY` 不可改变。
|
||||
- 报文未携带的字段不会被隐式清空;集合按完整合并结果写入。
|
||||
- 报文未携带的字段不被隐式清空(与 SIS §3.16 的冲突见 §3.1 与 Q13);集合按完整合并结果写入。
|
||||
- 缺席于某个日计划不构成删除理由;删除只由 FDEL 或受控历史清理触发。
|
||||
- 外部副作用失败可重试,不回滚已提交的本地业务结果。
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
- 本文档记录 msgexchange-api(现役旧项目)的完整业务逻辑,并以用户故事形式组织,作为新系统(Micronaut + Kotlin)迁移设计及一致性对拍的行为基线。
|
||||
- 内容依据仓库源码与资源配置编写:`src/main/java/com/gzzn/omms/msgexchange-api/**`、`src/main/resources/*.yml`;分支 `feature/add_dev_containers_supports`(HEAD `eb72a668`)。
|
||||
- 报文结构依据 `SIS_AODB_RMS-V0.1.md` 与 `unisysaodbsis.xsd`(同目录 docs/legacy/)。
|
||||
- 优先级:本文只描述现役行为;与 `SIS_AODB_RMS-V0.1.md` 冲突时以 SIS 为准。
|
||||
- 文档中"关联代码"均为相对仓库根目录的源码路径,可据此逐条复核。
|
||||
|
||||
## 1. 系统定位与集成边界
|
||||
@@ -160,7 +161,7 @@ msgexchange-api 为成都机场 OMMS 消息交换服务(`com.gzzn.omms:msgexch
|
||||
|
||||
### 3.8 HTTP 查询与运维接口
|
||||
|
||||
- `GET /all/flights`:读取 Redis 全部动态航班,过滤非共享航班(`MAID == NULL`)后返回 `ResponseDto<List<SCHD.FLTR>>`。
|
||||
- `GET /all/flights`:读取 Redis 全部动态航班,过滤掉共享航班(`MAID != NULL`)后返回 `ResponseDto<List<SCHD.FLTR>>`。
|
||||
- `GET /flights/migrate`:scroll 读取 ES `flight_hts` 全量数据,经 `transToNewFltrs` 还原 `SCHD.FLTR`(将 `ABN[].BODY` 按类型 DLY / CAN / RTN / ALT 映射回对象字段),逐条写入 ES `flight_hts2`。该接口为一次性数据迁移工具。
|
||||
- `POST /kafka/topics/{name}/msgs`:请求体先按 JSON(Map)解析,成功则直接发送至 Kafka 主题 `{name}`;解析失败则按 XML 解析为 `MSG` 再转 JSON 发送。该接口提供 XML / JSON 双模转发能力。
|
||||
- `POST /schd/sync`:见 3.9。
|
||||
@@ -368,7 +369,7 @@ msgexchange-api 为成都机场 OMMS 消息交换服务(`com.gzzn.omms:msgexch
|
||||
|
||||
- 角色 / 期望 / 目标:作为前端或调用方,期望获取当前全量动态航班(不含共享航班),以便页面渲染。
|
||||
- 触发条件:`GET /all/flights`。
|
||||
- 处理流程:`findAll`(Redis hmget)→ 过滤 `MAID == NULL` → `ResponseDto.success`。
|
||||
- 处理流程:`findAll`(Redis hmget)→ 过滤掉共享航班(`MAID != NULL`)→ `ResponseDto.success`。
|
||||
- 验收标准:返回结果不含共享航班记录,内容与 Redis `flightInfo` 一致。
|
||||
- 关联代码:`controller/FlightsController.java`、`service/flightInfo/FlightInfoServiceImpl.java`。
|
||||
|
||||
|
||||
+21
-14
@@ -52,7 +52,7 @@ MSG_EVENT PENDING ──→ SENT
|
||||
| 收报 | ID 区间内尚未入队的信箱行(谓词见 §5.1) | `PROC_STATE(PENDING)` | `MSG_ID` 主键 | 下轮扫描补入队 |
|
||||
| 取队头 | 最小未完成 `MSG_ID` | 本批处理消息 | 表状态即队列 | 无队头则等待 |
|
||||
| 解码与身份 | 信箱原文 | `DecodedMessage`、`IDENTITY_KEY` | 身份唯一约束 | 报文非法→`DEAD`;处理能力不足→`FAILED` 退避 |
|
||||
| 事务处理 | 当前完整状态 + 报文载荷 | 航班变更、终态、事件、回填待办 | 消息 ID + 业务身份 | 事务整体回滚重试 |
|
||||
| 事务处理 | 当前完整状态 + 报文载荷 | 航班变更、终态、事件、回填意图 | 消息 ID + 业务身份 | 事务整体回滚重试 |
|
||||
| 提交后回填 | 终态消息 | 信箱处理标记 | 标记单调(§11) | 终态事务内登记回填意图;失败退避重试,超期强制补写 |
|
||||
| 投递 | `MSG_EVENT` | 投递目标接受确认 | `EVENT_ID` | 退避至 `DEAD`;至少一次 |
|
||||
| 补偿作业 | 到期或已达 `NOW − R` 的终态记录 | 追平标记 | 消息 ID(仅空标生效) | 指数退避,独立线程执行;`R` 覆盖退避 |
|
||||
@@ -68,14 +68,14 @@ MSG_EVENT PENDING ──→ SENT
|
||||
| 已落信、未入队 | 信箱行位于应扫描的 ID 范围且 PG 无记录(不以处理标记为判据) | 重扫补建入队记录 |
|
||||
| 事务执行中 | PG 无该消息终态 | 事务整体回滚,按 `PENDING` 重新处理 |
|
||||
| 事务已提交、标记未写 | 终态行仍持有回填意图(`BACKFILL_NEXT_AT` 非空) | 仅补写标记;业务处理结果保持不变 |
|
||||
| 回填待办登记失败(与业务同事务) | 事务未提交 | 同"事务执行中",不构成独立窗口 |
|
||||
| 回填意图登记失败(与业务同事务) | 事务未提交 | 同"事务执行中",不构成独立窗口 |
|
||||
| 标记写入中途 | 标记仍为空 | 重新写入;重复写入同一值无副作用 |
|
||||
| 投递目标已接受、`SENT` 未置 | 事件仍 `PENDING` | 允许重发,消费方按事件身份去重 |
|
||||
|
||||
两个窗口已随"终态与回填意图同体同行"消除(口径与 design.md §10「事务与外部副作用」一致),不再是缺口:
|
||||
|
||||
1. **提交后回填前崩溃**:回填意图与处理终态是同一条记录的同一次写入、同一个事务;重启后扫描按该意图继续补写。
|
||||
2. **回填待办二次落账失败**:不存在第二处落账——意图就在终态行上。
|
||||
2. **回填意图二次落账失败**:不存在第二处落账——意图就在终态行上。
|
||||
|
||||
仍属未闭环的是回填本身在跨库单写期间的持续失败:由退避重试与 §5.2 的超期期限 `R` 兜底(登记于 design.md §10 与 user-stories.md US-09)。
|
||||
|
||||
@@ -90,9 +90,11 @@ MSG_EVENT PENDING ──→ SENT
|
||||
1. **ID 单调**:信箱 ID 按提交顺序分配,晚提交的较小 ID 不参与。承诺缺失时,`W` 只能作为快路径的提示,不能证明该区间收齐。
|
||||
2. **最大提交时延**:上游提交到 ID 可见的最长时间。补偿扫描窗口(`NOW − 最大提交时延`)的宽度由此确定。
|
||||
|
||||
取值可参照 SIS:报文在 CIIMS 的 `Expiry` 为 480 分钟,断连 120–480 分钟按 Level 2 处理,CIIMS 保证报文在成功接收或过期前按序保存(`SIS_AODB_RMS-V0.1.md` §2.4.2.3.3、§3.16、§3.17、§5.2)。
|
||||
|
||||
日常执行方式:快路径从 `ID > W` 起按升序有限批次扫描;另按周期对窗口内可能迟到或空洞的行做补偿扫描。需要区分:水位表示"读取进度",与"已处理标记"是两个事实,不能互相替代。
|
||||
|
||||
**空洞老化**:自增回滚等会在 ID 序列中留下永久空位,而 Q2 只承诺 ID 单调、不承诺无空洞。W+1 处的空洞持续超过最大提交时延仍未被补齐时,即判定为永久空洞并放行水位(实现取 `pipeline.max-commit-delay`);放行只跳过空洞本身,不越过任何已存在的行。没有这条规则,水位会永久停摆于第一个空位,其后的行再也不会入队。
|
||||
**空洞老化**:自增回滚等会在 ID 序列中留下永久空位,而 Q2 只承诺 ID 单调、不承诺无空洞。W+1 处的空洞持续超过最大提交时延仍未被补齐时,即判定为永久空洞并放行水位(实现取 `msgx.pipeline.max-commit-delay`);放行只跳过空洞本身,不越过任何已存在的行。没有这条规则,水位会永久停摆于第一个空位,其后的行再也不会入队。
|
||||
|
||||
两条扫描路径都按 **ID 区间**取行,不以处理标记为扫描谓词;标记只用于回填与库方清除,不参与消息发现。否则已入队但尚未回填的行会永久占据批次,这正是 US-01 条目 3 与 Q2 要求排除的场景。
|
||||
|
||||
@@ -100,7 +102,7 @@ MSG_EVENT PENDING ──→ SENT
|
||||
|
||||
所有处理终态都只依赖消息 ID 执行回填;报文残缺或缺少 META 不妨碍正常回填。本节规定回填通道长期失败时的超期兜底,避免终态信箱行无限期保持空标记。处理规则为:
|
||||
|
||||
**已达 `PROC_STATE` 终态、且接收时间超期(`DATE_RECEIVED < NOW − R`)仍无标记的信箱行,由回填通道补写一个库方认可的"已处理"类标记。**
|
||||
**已达 `PROC_STATE` 终态、且接收时间超期(信箱 `DATE_RECEIVED`,落库为 `PROC_STATE.RECEIVED_AT`;判据 `RECEIVED_AT < NOW − R`)仍无标记的信箱行,由回填通道补写一个库方认可的"已处理"类标记。**
|
||||
|
||||
- 期限 `R` 必须不小于(人工重放期限 + 人工处置期限)之和;两项期限的取值口径统一见 Q6,确认前不得下调 `R`。提前补写会使仍可重放的消息先被库方清除、失去原件资格。
|
||||
- 中间态(`PENDING` / `FAILED`)不适用本规则:处理未完成时不打标,也不允许被清除。
|
||||
@@ -126,8 +128,8 @@ MSG_EVENT PENDING ──→ SENT
|
||||
**第三步:等待过程中的四个边界。**
|
||||
|
||||
- 不插队:主泵按 FIFO 消化,积压期间到达的实时消息排在积压之后。本设计不允许并行队头,也不允许实时通道跳过积压。
|
||||
- 不失控:队头滞留上限(head-deadline,当前 10 分钟)对积压同样生效;队头长期失败按既有规则转 `DEAD(EXHAUSTED)` 并告警,不会因积压而延长容忍。在 Q6 收敛前,该上限的实际判据仍是 `updatedAt` 与系统取时(见 design.md §10),本条款是目标口径。
|
||||
- 报文类型的处理方式不变:旧的全量日计划(`SCHD-DNLD`)按最新一份**合并**即可收敛(缺席不删、缺失字段保留,见 flight-state.md §3.1),但仍逐条执行;动态增量(`FLOP-*` / `FDEL` / `ADFT`)持有时序语义,必须逐条。
|
||||
- 不失控:队头滞留上限(`msgx.pipeline.head-deadline`,当前 10 分钟)对积压同样生效;队头长期失败按既有规则转 `DEAD(EXHAUSTED)` 并告警,不会因积压而延长容忍。判据以首次处理时写入的 `PROCESSING_STARTED_AT` 为稳定起点、经可注入 `Clock` 判定(design.md §3.2、§10);长期积压与人工重放的期限口径仍由 Q6 定案。
|
||||
- 报文类型的处理方式不变:旧的全量日计划(`SCHD-DNLD`)按最新一份**合并**即可收敛(缺席不删、缺失字段保留;字段级冲突见 flight-state.md §3.1 与 Q13),但仍逐条执行;动态增量(`FLOP-*` / `FDEL` / `ADFT`)持有时序语义,必须逐条。
|
||||
- 可放弃但必须留痕:摸底批中经库方确认"不再处理"的行,处置方式为——`PROC_STATE` 置 `SKIPPED` 并记录跳过原因,到达终态后走 §5.2 通道补写标记;本方案不支持任何"整段 DELETE"的快速通道。
|
||||
|
||||
**验收口径**:积压消化期间持续输出三项指标——剩余积压条数、最老未处理信龄、预计消化时长;期间不允许出现 FIFO 越序、身份去重失效或头行滞留超时未告警。红线依据:architecture.md §5(消息严格 FIFO)、单写者约束。三项指标并入 user-stories.md OPS-2 的可观测性验收。
|
||||
@@ -163,6 +165,7 @@ MSG_EVENT PENDING ──→ SENT
|
||||
- 执行清除时,边界内不存在未打标记的行;未达终态的行顺延至处理完成后清除(§5.2 仅对终态行补标);
|
||||
- 时间比较与换算统一采用机场时区 Asia/Shanghai 及明确的类型转换(口径同 user-stories.md §6);
|
||||
- 清除保留期 `R_keep` 不小于 max(回填重试上限、重放期限、审计期限);且 §5.2 的 `R` 不大于 `R_keep`,否则尚在重放窗口内的消息会先于重放被清除;
|
||||
- legacy 现役按接收时间超过 1 天即归档并删除 `CMINMSGS`(legacy 行为基线 §3.6);若沿用该窗口,则与上一行的保留期下限冲突,须在 Q9 中与库方一并确认;
|
||||
- 信箱 ID 全程不断链:方案 A 天然满足;方案 B 依赖 `AUTO_INCREMENT` 种子,种子缺失时新 ID 与旧记录主键冲突,水位随之失效。
|
||||
|
||||
## 7. 出站信箱(COUTMSGS)
|
||||
@@ -171,6 +174,8 @@ MSG_EVENT PENDING ──→ SENT
|
||||
|
||||
出站前在 `REQ_TRACK` 登记 `REGISTERED`;写入 `COUTMSGS` 并确认落信后置 `SENT` 并关联出站记录 ID。"落信"指写入信箱成功,不等于下游已读取或已发送,交付承诺仅到落信为止(US-08)。
|
||||
|
||||
主/共享删除顺序违例时 SIS 要求向 AODB 回发 EROR(`SIS_AODB_RMS-V0.1.md` §1.6.1-1.d,事件定义见 SIS §4.8);当前没有该出站路径,取舍见 Q14。
|
||||
|
||||
本系统写入的行由谁消费、按什么顺序消费,**当前未知**。以下事项在 Q10 关闭前按未知处理,不得作为已具备能力描述:
|
||||
|
||||
- 消费方与消费顺序;
|
||||
@@ -178,7 +183,7 @@ MSG_EVENT PENDING ──→ SENT
|
||||
- 出站行的清除责任与保留期;
|
||||
- 落信成功但本地未置 `SENT` 时的重复写入风险及下游去重契约。
|
||||
|
||||
参考事实:legacy 的 SIS 接口规范记载各系统持有各自的 `COUTMSGS` 副本,由 JDBC Adapter 读取后发送至 CIIMS。该机制是否在现场沿用,属于 Q10 的确认范围,不作为现状依据。
|
||||
参考事实:legacy 的 SIS 接口规范记载各系统持有各自的 `COUTMSGS` 副本,由 JDBC Adapter 读取后发送至 CIIMS;同时记载从 RMS 发出的报文不执行 CIIMS 确认(`SIS_AODB_RMS-V0.1.md` §2.4.2.2.2、§2.4.2.2.4)。这两点是否在现场沿用、与 `COUTMSGS_ACK_*` 列的关系如何,均属 Q10 的确认范围,不作为现状依据。
|
||||
|
||||
## 8. 自有记录归档
|
||||
|
||||
@@ -200,19 +205,21 @@ MSG_EVENT PENDING ──→ SENT
|
||||
| Q6 | 重放 deadline 与人工处置期限的取值(决定 §5.2 的 `R`) | §5.2、§9 |
|
||||
| Q7 | 处理标记值集与写权限;原文保留期;处理时间语义 | §5.2、§6 |
|
||||
| Q8 | 逐类覆盖清单(积压摸底的类型分布依据) | §5.3 |
|
||||
| Q9(新增) | 清除执行方与 DDL 授权;方案 A / B 选型 | §6 |
|
||||
| Q10(新增) | 出站消费方、ACK 列语义、出站清理与去重契约 | §7 |
|
||||
| Q11(新增) | 上游 `SEQN` 重置规则与业务身份的日期边界 | design.md §2.2 |
|
||||
| Q12(新增) | 历史积压批次“不再处理”的确认主体、审批留痕与跳过值集 | §5.3 |
|
||||
| Q9 | 清除执行方与 DDL 授权;方案 A / B 选型 | §6 |
|
||||
| Q10 | 出站消费方、ACK 列语义、出站清理与去重契约 | §7 |
|
||||
| Q11 | 上游 `SEQN` 重置周期与业务身份的日期边界 | design.md §2.2 |
|
||||
| Q12 | 历史积压批次“不再处理”的确认主体、审批留痕与跳过值集 | §5.3 |
|
||||
| Q13 | 日计划缺失可选字段的删除语义(与 SIS §3.16 注释 4 冲突) | §5.3、flight-state.md §3.1 |
|
||||
| Q14 | 主/共享删除顺序与 EROR 回报义务 | §7、flight-state.md §3.3 |
|
||||
|
||||
Q6–Q12 的完整登记见 [user-stories.md](user-stories.md) §6 的 Q 表。
|
||||
Q2、Q6–Q14 的完整登记见 [user-stories.md](user-stories.md) §6 的 Q 表。
|
||||
|
||||
## 11. 不变量
|
||||
|
||||
- 五个事实互不替代:入队不引用信箱标记,回填不引用投递,投递不引用回填。
|
||||
- 处理终态不可逆:已提交的 `SUCCEEDED` 不因回填或投递失败回改。
|
||||
- 处理标记单调:任何路径只将空标写为已处理,不回撤、不覆盖。
|
||||
- 水位不越过未入队的 ID;遇空洞即停。
|
||||
- 水位不越过任何已存在的行;遇空洞即停,只有 §5.1 判定为永久空洞时才放行。
|
||||
- 执行清除前,边界内全部行已持有处理标记;物理删除仅发生在归档成功之后(追加写入与分区留档均构成归档成功)。
|
||||
- 信箱 ID 全局单调、不断链:以 Q2 的 ID 单调承诺与 §6 各方案前提成立为条件(方案 B 依赖 `AUTO_INCREMENT` 种子)。
|
||||
- 对外投递按至少一次设计;端到端恰好一次不在交付范围内。
|
||||
|
||||
+14
-12
@@ -6,7 +6,7 @@
|
||||
|
||||
- 系统边界见 [architecture.md](architecture.md),模块流程见 [design.md](design.md)。本文不重复设计全文,也不以工单状态代替代码验收。消息生命周期与信箱清除见 [message-lifecycle.md](message-lifecycle.md),航班规则见 [flight-state.md](flight-state.md)。
|
||||
- “当前基础”来自本轮代码核对,只表示有接口或部分实现,不表示故事完成。`KEEP` 是保留业务兼容,`FIX` 是明确修正旧缺陷,`DEFERRED` 不进入阶段 A。
|
||||
- “信箱落信、PG 入队、业务处理完成、信箱回填、目标端投递确认”是五个独立事实,接口、日志和测试必须分开表达。投递确认不等于业务消费者已消费。
|
||||
- 五个独立事实(落信、入队、处理完成、回填、投递确认)的定义与判定见 [message-lifecycle.md](message-lifecycle.md) §1;接口、日志和测试必须分开表达,投递确认不等于业务消费者已消费。
|
||||
- 所有内部迁移只落自有 PG;共享 MySQL 不建表、不增列、不写历史表。本文用 `DATE_PROCESSED / STATUS` 表示逻辑字段,实际列名以库方契约为准。
|
||||
- 验收条目可按 `US-xx/条目号` 引用。故事较大时按下文子范围拆成小 PR,不把一个故事等同于一个提交。
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
4. PG 不可用或批次中途失败时不改信箱标记;恢复后补建遗漏,记录失败次数与扫描进度。
|
||||
5. 较小 ID 迟提交、ID 有空洞、兼容入口先入队较大 ID 时,必须遵守经 Q2 确认的发现与顺序协议;不能用“最终会重扫”冒充严格 FIFO。
|
||||
|
||||
**当前基础与落点**:`ingress/InboxPoller.kt` 按 ID 区间扫描(`ID > W`,不以处理标记为谓词),水位落 `INBOX_CURSOR` 并与入队同事务推进;`JdbcCminmsgInboxRepository.readRange/maxId` 与 `ProcStateRepository.insertIfAbsent` 承担发现与幂等入队。空洞老化阈值取 `pipeline.max-commit-delay`。剩余:Q2 未书面确认前,老化阈值与严格顺序仍是假定口径;真实 MySQL 的中断恢复与迟提交联合测试待现场环境。
|
||||
**当前基础与落点**:`ingress/InboxPoller.kt` 按 ID 区间扫描(`ID > W`,不以处理标记为谓词),水位落 `INBOX_CURSOR` 并与入队同事务推进;`JdbcCminmsgInboxRepository.readRange/maxId` 与 `ProcStateRepository.insertIfAbsent` 承担发现与幂等入队。空洞老化阈值取 `msgx.pipeline.max-commit-delay`。剩余:Q2 未书面确认前,老化阈值与严格顺序仍是假定口径;真实 MySQL 的中断恢复与迟提交联合测试待现场环境。
|
||||
|
||||
**前置**:共享库读契约;Q2 决定严格顺序的端到端验收。水位与扫描谓词口径以 [message-lifecycle.md](message-lifecycle.md) §5.1 为准。
|
||||
|
||||
@@ -80,12 +80,12 @@
|
||||
2. 安全解码 XML,至少覆盖 META、SCHD、FLOP、参考应答与忽略类路由;合法但能力未支持是 `UNSUPPORTED`,不能一律归为非法报文。保留原文以支持诊断和回放。
|
||||
3. 解码后首次绑定 `SNDR|TYPE|STYP|SEQN`;冲突转 `SKIPPED` 并记录原 ID;自身重试保留绑定。生产 `include-day-boundary=false`,更改算法须另行评审上游序号规则。
|
||||
4. `MALFORMED` 直接 `DEAD`;`CODEC_ERROR / UNSUPPORTED / INFRA` 按次数和退避处理,耗尽转 `DEAD(EXHAUSTED)`。不能无限重试未实现类型,也不能立即当非法报文丢弃。
|
||||
5. HOL deadline 必须基于稳定起始时刻(必要时在 `PROC_STATE` 增加入队时间列),不能用每次重试刷新的 `updatedAt` 代替;调度判断注入 `Clock`。默认 5 次重试、10 分钟滞留限制;积压与人工重放的 deadline 边界按 Q6 验证。
|
||||
5. HOL deadline 必须基于稳定起始时刻(`PROC_STATE.PROCESSING_STARTED_AT`),不能用每次重试刷新的 `updatedAt` 代替;调度判断注入 `Clock`。默认 5 次重试、10 分钟滞留限制;积压与人工重放的 deadline 边界按 Q6 验证。
|
||||
6. 主泵在同一 PG 事务提交航班主表/明细、事件与处理结果;终态回填意图通过 US-09 同事务保存。任一步失败整体回滚;提交后只重试外部回填,不重复生成业务事件。
|
||||
7. 领域决策逻辑只读取当前完整态与已解码报文,返回下一完整态和待发事件,不执行 I/O;Processor 作为事务协调器,将状态写入、事件、处理终态与回填意图收敛在同一事务边界内,不直接触碰 Kafka。失败只在持有消息上下文的边界落账,中断向上传递,不作为普通失败吞掉。
|
||||
8. 权威存储不可用或未完成恢复时停止业务处理;不能把“整个状态丢失”误判为“单航班不存在”而批量成功结束增量报文。
|
||||
|
||||
**当前基础与落点**:`processing/Pump.kt`(含 `MessageProcessor`)、`DynamicProcessors.kt`、`Identity.kt`、`codec/JacksonXmlCodec.kt`、`infra/retry/`。严格 FIFO 主泵、SCHD(DNLD/RESP/ADFT)/FLOP/FDEL 处理器、PG 单事务(含回填待办预登记)、身份绑定与重试已实现;调度取时由可注入 `Clock` 提供,HOL deadline 以 `PROCESSING_STARTED_AT` 为稳定起点。尚未完成:忽略规则分支(US-04),以及逐类矩阵与 golden 样例(US-05)。长期积压和人工重放如何计算 deadline 仍由 Q6 定案。
|
||||
**当前基础与落点**:`processing/Pump.kt`(含 `MessageProcessor`)、`DynamicProcessors.kt`、`Identity.kt`、`codec/JacksonXmlCodec.kt`、`infra/retry/`。严格 FIFO 主泵、SCHD(DNLD/RESP/ADFT)/FLOP/FDEL 处理器、PG 单事务(含回填意图预登记)、身份绑定与重试已实现;调度取时由可注入 `Clock` 提供,HOL deadline 以 `PROCESSING_STARTED_AT` 为稳定起点。尚未完成:忽略规则分支(US-04),以及逐类矩阵与 golden 样例(US-05)。长期积压和人工重放如何计算 deadline 仍由 Q6 定案。
|
||||
|
||||
**前置**:US-01;Q1 已定单库方向,Q6 决定 deadline 边界。数据库迁移只落自有库。
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
|
||||
**当前基础与落点**:落点已变为 `processing/DynamicProcessors.kt`(`FlopProcessor`/`FdelProcessor`/`AdftProcessor`)与 `domain/flight/FlightStateEngine`、`FlightStateRepository`。FDEL/ADFT 与通用 FLOP 处理器已接入(含 DELETED 幂等与重激活、tombstone 同事务登记);29 类逐类语义矩阵与 golden 样例仍未补全,不能因处理器存在就视为覆盖完成。
|
||||
|
||||
**前置**:US-03;PSDT 另依赖 US-14;Q1、Q8。
|
||||
**前置**:US-03;PSDT 另依赖 US-14;Q1、Q8、Q14。
|
||||
|
||||
### US-06 导入 RESP/DNLD 日计划快照
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
|
||||
**当前基础与落点**:DNLD 与 RESP 已共同路由到 `processing/ScheduleProcessor.applyScheduleRecords`,整包校验、归属日冲突整包拒绝与单事务写入已实现;`REQ_TRACK` 表与 `ReqTrackRepository` 已建。仍需补 RESP 应答守卫(开放 RQFD 匹配、时间比对)与请求完成关联逻辑。
|
||||
|
||||
**前置**:US-03、US-08 请求登记/匹配基础;Q1、Q5。
|
||||
**前置**:US-03、US-08 请求登记/匹配基础;Q1、Q5、Q13。
|
||||
|
||||
### US-07 可靠、有序地投递 Kafka
|
||||
|
||||
@@ -176,7 +176,7 @@
|
||||
|
||||
**当前基础与落点**:`ReqTrackRepository` 与 JDBC 实现、`REQ_TRACK` 表已存在;运行时协调器、`COUTMSGS` 出站适配与请求编码未实现(`XmlCodec.encodeRqrd` 仅占位),超时与应答匹配未闭环。需补协调器、出站适配、并发约束、应答路由与故障测试。
|
||||
|
||||
**前置**:US-01、US-03;Q5、Q8、出站信箱去重契约。请求基础不依赖 US-06。
|
||||
**前置**:US-01、US-03;Q5、Q8、Q14、出站信箱去重契约。请求基础不依赖 US-06。
|
||||
|
||||
### US-09 持久化补偿回填信箱
|
||||
|
||||
@@ -275,7 +275,7 @@
|
||||
|
||||
历史存储确认成功后,才允许删除对应实时航班;逐条隔离坏数据,不能删除写历史失败的集合。判史规则与保留期(`HistoryProps`)、业务时区 `Asia/Shanghai`、历史写入与删除事件之间的恢复协议需在启用前完成 golden 对拍。
|
||||
|
||||
阶段 A 不依赖 ES,不启用 `PROJECTION_REBUILD`。`HistorySweepJob` 已作为每日清理脚手架接入,但历史存储未接通(或 `history-store-enabled=false`)时删除 0 条;脚手架存在不等于清场已交付,红线见 flight-state.md §6。
|
||||
阶段 A 不依赖 ES,不启用 `PROJECTION_REBUILD`。`HistorySweepJob` 已作为每日清理脚手架接入,但历史存储未接通(或 `msgx.history.history-store-enabled=false`)时删除 0 条;脚手架存在不等于清场已交付,红线见 flight-state.md §6。
|
||||
|
||||
## 5. 运行与切流验收
|
||||
|
||||
@@ -305,17 +305,19 @@
|
||||
| 编号 | 问题与当前口径 | 解除阻塞的产物 |
|
||||
|---|---|---|
|
||||
| Q1 权威存储(方向已定) | 当前 PG 单库权威,主表 + 无损明细;现场供库目标为 Oracle 11g。 | 单库决策已采纳,Oracle 完整适配与部署验收仍待交付;不得退回 Redis 双写。 |
|
||||
| Q2 入队顺序 | 空洞老化阈值取自"最大提交时延",但库方尚未书面承诺 ID 单调与提交时延,因此迟提交不越序仍无端到端保证。 | 库方 ID/提交顺序约束,或明确的发现完整性与暂停/恢复协议;晚提交、空洞、兼容入口与重扫联合测试。不能凭空假定 ID 连续。 |
|
||||
| Q2 入队顺序 | 空洞老化阈值取自"最大提交时延",但库方尚未书面承诺 ID 单调与提交时延,因此迟提交不越序仍无端到端保证。取值可参照 SIS:报文在 CIIMS 的 `Expiry` 为 480 分钟,断连 120–480 分钟按 Level 2 处理,CIIMS 在成功接收或过期前保序保存(SIS §2.4.2.3.3、§3.16、§5.2)。 | 库方 ID/提交顺序约束,或明确的发现完整性与暂停/恢复协议;晚提交、空洞、兼容入口与重扫联合测试。不能凭空假定 ID 连续。 |
|
||||
| Q3 HTTP 契约 | 目标 ResponseDto 与现有 text/plain ID 不同;请求媒体类型目标已列出,错误码、状态码、查询格式等仍需对拍。 | 每个保留接口的真实请求/响应样例、错误表和契约测试;10MB 的字节口径、字符集及兼容变更说明一起固定。 |
|
||||
| Q4 Kafka wire | 当前 msg/schd 均按 `FLID` 逐航班发送(schd 由 `flushSchd` 合并为每个 FLID 的最新状态),与 legacy“多 FLID 数组”形态不同;msg 是否需按 `SNDR` 分区尚未接线。 | 下游确认发送粒度、key、去重标识放置、分区内顺序及批次确认策略;未定案前不改动现役消费契约。 |
|
||||
| Q5 请求匹配 | 目标优先 SEQN 回显,但回显是否可靠需确认;DTTM 降级存在跨代误匹配,尤其旧应答到达新请求期间。 | 15 类请求/响应样例、回显字段与时间格式;降级风险是否接受及拒绝条件。默认超时仍为 RQFD 60 秒、RQRD 30 秒。 |
|
||||
| Q6 deadline 与重放 | 入队时间作为稳定锚点会把长期排队消息计入滞留;历史重放保留 CREATED_AT 后可能立即过期。 | 明确首次处理/排队过期策略与“本次恢复尝试”计时方式,保留原始时间审计;测试积压恢复和旧 DEAD 重放,不用刷新 UPDATED_AT 绕过超时。 |
|
||||
| Q6 deadline 与重放 | 入队时间作为稳定锚点会把长期排队消息计入滞留;历史重放保留 CREATED_AT 后可能立即过期。外部参照:SIS 报文 `Expiry` 480 分钟(SIS §3.16),legacy 现役按接收超 1 天归档并删除(legacy 基线 §3.6)。 | 明确首次处理/排队过期策略与“本次恢复尝试”计时方式,保留原始时间审计;测试积压恢复和旧 DEAD 重放,不用刷新 UPDATED_AT 绕过超时。 |
|
||||
| Q7 信箱外部契约 | 原目标为成功→SUCCESS、忽略→SKIPPED、重复→DUPLICATE、死信→DEAD;当前 JDBC 写 PROCESSED。新 STATUS 值尚不能假定库方支持。 | 库方认可的状态值、META/缺失字段、权限、原文保留期、出站去重与处理时间语义;若只允许 legacy 集合,显式映射内部原因,不新增外部枚举。 |
|
||||
| Q8 业务覆盖清单 | “29 FLOP、14 RQRD、21 参考类、2 机位类”只是数量,不能直接当字段规范。 | 将 SIS/XSD、现役 KEEP/FIX 基线整理为逐类矩阵与脱敏样例,列明路由、字段、缺失/清空、通知、数据来源优先级、多桥规则及测试文件。资料不全的类型不标完成。 |
|
||||
| Q9 信箱清除契约 | 清除由谁执行与 DDL 授权、方案 A/B 选型、现场 MySQL 版本与分区 DDL 能力(message-lifecycle.md §6)。 | 库方书面确认清除授权与方案选型。 |
|
||||
| Q10 出站信箱契约 | `COUTMSGS` 消费方与顺序、`COUTMSGS_ACK_DATE_RECV / COUTMSGS_ACK_RESEND_TIMES / COUTMSGS_DATE_SENT / COUTMSGS_ERROR` 等列语义与写入方、出站清理责任与去重契约(message-lifecycle.md §7;legacy 参考见 SIS 规范 COUTMSGS 机制章节)。 | 库方书面确认出站消费、清理与去重契约。 |
|
||||
| Q11 上游序号重置 | 上游 `SEQN` 重置规则决定业务身份是否加入日期边界(design.md §2.2,默认关闭)。 | 上游确认重置规则;身份算法变更须另行评审。 |
|
||||
| Q10 出站信箱契约 | `COUTMSGS` 消费方与顺序、`COUTMSGS_ACK_DATE_RECV / COUTMSGS_ACK_RESEND_TIMES / COUTMSGS_DATE_SENT / COUTMSGS_ERROR` 等列语义与写入方、出站清理责任与去重契约(message-lifecycle.md §7;SIS §2.4.2.2.2、§2.4.2.2.4、§2.4.2.3)。 | 库方书面确认出站消费、清理与去重契约。 |
|
||||
| Q11 上游序号重置 | `SEQN` 的取值范围与回绕已由 SIS §2.8.1 定义(`Number(6)`、1–999999、由发送方设置),未知的是重置周期;它决定业务身份是否加入日期边界(design.md §2.2,默认关闭)。`SNDR` 取值域也需对拍:SIS 为 AODB/RMS,legacy 实发 OSH5 等。 | 上游确认重置周期与 `SNDR` 值域;身份算法变更须另行评审。 |
|
||||
| Q12 积压跳过授权 | 历史积压批次中“不再处理”的确认主体、审批留痕与跳过值集(message-lifecycle.md §5.3)。 | 业务与库方书面确认该批跳过范围;`PROC_STATE=SKIPPED` 记录原因并保留审计,不允许整段 DELETE。 |
|
||||
| Q13 日计划字段缺失语义 | SIS 要求最新日计划中未发送的可选字段视为 AODB 已无该数据、子系统应删除本地已有值(SIS §3.16 注释 4,RESP 同格式见 SIS §3.17),与现行"未携带字段保留"相反(flight-state.md §3.1、message-lifecycle.md §5.3)。 | 与 AODB/库方书面确认字段级删除语义;确认前不得按任一方向验收对拍差异。 |
|
||||
| Q14 主/共享删除顺序与 EROR | SIS 要求删主航班前先删子共享航班,顺序不符时 RMS 向 AODB 回发 EROR(SIS §1.6.1-1.d,事件定义 SIS §4.8)。现行设计为自动原子级联,未定义回报路径(flight-state.md §3.3)。 | 确认上游删除顺序约定,并选定"回发 EROR"或"幂等自动级联";出站事件类型随之纳入 US-08 范围。 |
|
||||
|
||||
业务日期/日计划采用 `Asia/Shanghai`;持久化与比较使用明确的时间类型和转换规则,不靠服务器默认时区,也不直接比较不同单位的数字。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user