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:
windyboy
2026-09-10 20:54:01 +08:00
parent eea11203a2
commit 50e0e7f389
7 changed files with 70 additions and 53 deletions
+21 -14
View File
@@ -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 分钟,断连 120480 分钟按 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 |
Q6Q12 的完整登记见 [user-stories.md](user-stories.md) §6 的 Q 表。
Q2、Q6Q14 的完整登记见 [user-stories.md](user-stories.md) §6 的 Q 表。
## 11. 不变量
- 五个事实互不替代:入队不引用信箱标记,回填不引用投递,投递不引用回填。
- 处理终态不可逆:已提交的 `SUCCEEDED` 不因回填或投递失败回改。
- 处理标记单调:任何路径只将空标写为已处理,不回撤、不覆盖。
- 水位不越过未入队的 ID;遇空洞即停
- 水位不越过任何已存在的行;遇空洞即停,只有 §5.1 判定为永久空洞时才放行
- 执行清除前,边界内全部行已持有处理标记;物理删除仅发生在归档成功之后(追加写入与分区留档均构成归档成功)。
- 信箱 ID 全局单调、不断链:以 Q2 的 ID 单调承诺与 §6 各方案前提成立为条件(方案 B 依赖 `AUTO_INCREMENT` 种子)。
- 对外投递按至少一次设计;端到端恰好一次不在交付范围内。