Files
msgexchange-v2/docs/specification.md
T
windyboy 6fa4da60f1 docs(acm2-75): 收敛 2.1-2.4 约定条目并重排编号
- 2.1 共享信箱:从 14 条收敛为 C-1、C-2
- 2.2 上游:从 8 条收敛为 C-3 到 C-6
- 2.3 HTTP 入口:C-7、C-8
- 2.4 下游:C-9 到 C-11
- 删除 2.5 已作废条款节
- 更新全文交叉引用
2026-09-16 14:43:38 +08:00

246 lines
27 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.
# 规范:术语、约定、前提、不变量与能力边界
本文整理 msgexchange-v2 对外接口约定(`C-x`)、前提条件(`PRE-x`)、系统不变量(`INV-x`)、能力边界(`CLM-x`)、待确认事项(`Qn`)与已知偏差(`G-NAME`),并统一给出术语。条款依据 [requirements.md](requirements.md) 与 [architecture.md](architecture.md) 编写;字段联调草案另见 [contracts/interface-contract.md](contracts/interface-contract.md),对外承诺以本文件为准。
`C-x``PRE-x``INV-x``CLM-x``Qn``G-NAME` 只在本文件定义,编号规则见 [README.md](README.md)。
约定条目的标记:
- 需要对方确认的,末尾标 `(待确认 Qn`
- 内容已定、个别字段未定的,另起一行以「待确认:」列出并指向 `Qn`
- 本系统单方遵守、不依赖对方认可的,末尾标 `(本系统单方承诺)`
- 未标注的,表示需求或架构已定,本系统按此执行。
作废条款集中放在各节末尾,保留原文与作废标记。
## 1. 术语
| 术语 | 含义 |
|---|---|
| 上游 | 产生报文的 AODB,报文经 CIIMS adapter 写入信箱。 |
| 信箱 | 共享 MySQL 的 `CMINMSGS`(入站)与 `COUTMSGS`(出站),归库方所有;边界见 `C-2`。 |
| 库方 | 信箱所在的共享 MySQL 管理方,即 CIIMS adapter 方。 |
| 处理标记 | 即信箱行上的处理时间:为空表示未处理,处理完成时写入完成时刻。 |
| 落信 | 报文写入信箱成为一行;入站由 CIIMS adapter 或兼容入口写入,出站由本系统写入 `COUTMSGS`;入站报文写进信箱后可能尚未登记。 |
| 登记 | 本系统在自有 PG 为这条报文建立处理记录,排队等待处理。 |
| 处理完成 | 这条消息的结果已经确定——业务改动生效,或明确跳过、进入死信;之后才回填信箱标记、发 Kafka。 |
| 回填 | 处理完成后,把完成时刻写回信箱行的处理时间字段,告知上游该消息已处理。 |
| 投递 | 读待发事件,发往 Kafka。 |
| Redis 投影 | 供网页客户端(`GET /all/flights`)查询的航班投影,内容来自自有 PG 当前态;读写边界见 `INV-24`。 |
| 自有 PG | 本系统唯一的业务数据库;航班当前态、管道记录与静态参考数据都在这里。 |
| 权威 | 航班当前态以自有 PG 为准(`INV-11b`)。 |
| 出站请求 | 经 `COUTMSGS` 发向 AODB 的 `RQRD` 参考数据请求与 `RQFD` 日计划请求,消费方为 CIIMS adapter。 |
| 运营航班显示界面 | 需求所称网页客户端:Kafka 侧称运营航班显示界面,查询侧称网页客户端(`GET /all/flights` / Redis)。 |
| 航班历史 | 已结束航班写入 Elasticsearch 后的副本;写成功后才从实时数据删除。 |
| 静态参考数据 | 13 类基础数据与资源状态,写自有 PG 的独立数据表,admin-api 直接只读。 |
## 2. 约定
### 2.1 共享信箱(库方)
- **C-1** 本系统清理已处理的信箱行:回填完成且超过保留期后才删,处理未完成或回填未完成的行不删。
- **C-2** 共享 MySQL 不做 Schema 变更,本系统只读写 `CMINMSGS``COUTMSGS` 两张表。
### 2.2 上游(AODB / SIS
- **C-3** 业务身份由 `SNDR``TYPE``STYP``SEQN` 四字段组合;`SEQN` 自增,极少重置(消息服务器重启),重置后不会与旧消息冲突。
- **C-4** 出站请求写入 `COUTMSGS`;交付承诺止于落信。
- **C-5** 航班删除为标记删除,主航班与共享航班各自独立标记。
- **C-6** 日计划快照里没有携带的字段视为 AODB 已删除该值,本地同步清除(`US-07` AC3)。
### 2.3 HTTP 入口
- **C-7** `POST /cminmsgs/send`:把 XML 写进入站信箱,与 adapter 投递走同一套处理。成功返回消息编号(仅表示已入库,未处理);失败无编号。支持 `text/xml``application/xml``text/plain`(UTF-8);空、超长、格式错的不写;解析不拉外部资源。内网,访问由网络配置控制。
待确认:长度上限、失败响应(`Q3`)。
- **C-8** `POST /schd/sync`:向出站表写入一条日计划请求。
待确认:请求参数、HTTP 响应(`Q17`)。
### 2.4 下游(admin-api、网页客户端与运营航班显示界面)
- **C-9** 航班变更发到 Kafka 主题 `msg`(单条)和 `schd`(批量)。同一条可能发多次。
- **C-10** 静态参考数据写入本系统数据库,供 admin-api 只读;本系统不调用 admin-api。
- **C-11** 航班投影写入 Redis,供 `GET /all/flights` 与网页客户端查询。
待确认:key 与 value 结构(`Q20`)。
## 3. 前提
前提失效时不变量必须整体重估。
| 编号 | 前提 | 若不成立的影响 | 状态 |
|---|---|---|---|
| PRE-1 | 信箱消费权排他:同一时刻只有一个系统有权处理、打标与判定可清除 | 采集谓词、身份去重与清除前提全部失效 | 由切流规程保证,上线前另立 |
| PRE-2 | 信箱编号的分配顺序即到达顺序 | 「编号即到达顺序」的顺序声称失去依据 | 待确认 `Q2` |
| PRE-3 | 信箱编号空间不复位、不复用、不回退 | 同一编号可能重复登记 | 待确认 `Q2` |
| PRE-4 | 信箱时间列的时钟基准可解释,偏斜有界 | 与本地时间的比较会提前或推迟判定 | 待确认 `Q7` |
| PRE-5 | 单活动实例运行,信箱读取不加锁 | 并行读会让「已处理」判定互相踩踏 | 部署约束 |
| PRE-6 | 信箱与自有 PG 之间没有跨库事务 | 回填与清除都不能声称原子 | 架构事实 |
| PRE-7 | 报文不可变:同一业务身份的重发是同一内容 | 上游改发正文会被判为重复并静默跳过 | 待确认 `Q15` |
| PRE-9 | 测试环境与生产隔离:测试实例使用独立的数据库、Redis 与 Kafka 主题,不连接生产信箱 | 测试结论与隔离验收(`OPS-3`)失效 | 部署与配置约束 |
## 4. 不变量
### 4.1 管道
- **INV-1** 五个事实互不替代:落信、登记、处理完成、回填、投递各有独立证据,前一个不蕴含后一个。
- **INV-2b** 扫描谓词与幂等登记:每轮按编号升序读取「处理时间为空」的信箱行,每批有上限;同一编号只登记一次;重复扫描与重启恢复不重复登记、不丢行。失败后的重处理是 `US-03` AC3 的要求;成功业务效果至多一次由 `INV-20b` 承载,当前被 `G-FLOP-IDEMPOTENT` 阻断。
- **INV-3** 队头唯一:任一时刻只有一个可执行的队头(编号最小的未完成消息),队头未完成时后面的消息不得越过。
- **INV-6** 处理终态不可逆:已提交的成功不因回填或投递失败回改。
- **INV-7** 处理标记单调:任何路径只把空标记写成已处理值,不回撤、不覆盖。
- **INV-8** 回填只针对已有终态的消息;「还欠一次回填」与终态由同一条语句落库,不存在第二处落账。
- **INV-9** 一信一行、一身份一记录:处理记录按信箱编号唯一,同一业务身份至多绑定一条有效记录。再次发现同一身份的信箱行时不得直接跳过:须与既有记录比对内容,一致才按重复跳过留档(`PRE-7`:重发是同一内容);不一致即 `PRE-7` 失效信号,留档、告警、不产生业务效果,处置待 `Q15` 定案。
- **INV-10** 对外投递至少一次;端到端恰好一次不在交付范围。
- **INV-16** 回填与 Kafka 投递失败可重试,不回滚已提交的本地业务结果;出站请求写入结果不明时记录告警、不直接重发。
- **INV-17b** 航班类消息(增量、删除)的状态变更与待发事件在同一事务提交;处理终态与回填意图在另一事务提交,且晚于 Redis 投影写成功。待发事件在处理完成前不可投递(`US-03` AC4),本句对所有类别生效。日计划的分批与静态参考数据的单事务见架构「主流程」。
- **INV-19** 日计划整包校验失败时整包不落地,既有状态与版本不变(`US-07` AC1)。运营日冲突时的处置未在需求与架构定案(`Q23`)。
- **INV-20b** 处理器幂等(目标不变量,被 `G-FLOP-IDEMPOTENT` 阻断,当前不成立):同一消息在失败重处理与重复发现下都只产生一次业务效果。身份唯一只防「重复记录」,不防「重新执行」;逐类幂等规则补齐并回归前,依赖本条的收敛声明(`CLM-3`)不可作出。
- **INV-30** 非法报文进死信、合法但不支持的类型跳过留档,两者都无业务副作用、按已处理回填(`US-03` AC2);处理错误记在对应消息的处理记录上,不被外层吞掉(`US-03` AC5)。
### 4.2 航班域
- **INV-11b** 自有 PG 的航班当前态是唯一权威;信箱、Redis 投影、Kafka、展示视图都不是权威。
- **INV-12** `FLID` 唯一;已写入非空的运营日不可改。
- **INV-13** 每次成功写入版本号加一;重复消息不重复加,版本不回退。
- **INV-14b** 增量报文未携带的字段不被隐式清空。日计划快照不适用本条(`INV-15b`)。
- **INV-15b** 日计划快照以 AODB 下发为准:快照里没有的航班删除——标记已删除、登记删除事件、从 Redis 投影移除;未携带的字段同步清除(`US-07` AC2/AC3)。
- **INV-18** 航班表的写者是主泵处理器与航班历史清理,两者必须互斥,不得出现清理删除与处理器更新同一个 `FLID` 的竞态。
- **INV-21** 主航班与共享航班的删除各自独立标记(`US-06` AC2、`C-5`)。
- **INV-22** 航班标记删除后从 Redis 投影移除。移除成功后才算处理完成(`INV-17b``INV-23`);失败即未完成,下轮重做。共享航班在 Redis 投影中的呈现方式、删除通知使用共享还是主航班 `FLID`,待 `Q20``Q4`
- **INV-29** 已删除航班收到 `ADFT` 时按报文内容恢复为有效航班(`US-04` AC3):恢复走正常处理路径,推进版本、刷新投影并登记事件,不因已删除而跳过或拒绝。
- **INV-31** 日计划以整包为完成单位:每批提交只是持久化进度,处理完成在整包写入完成且 Redis 按快照刷新成功后判定(`US-07` AC4/AC5);刷新在整包写入完成后才开始(架构「主流程」)。刷新期间查询可见的投影状态不作承诺,是否提供原子切换视图取决于 `Q20`。失败后整包重处理,收敛依赖版本只进不退与逐航班重写幂等(`INV-13`);日计划的逐航班重写幂等未补齐(`G-SCHD-SNAPSHOT`),闭合前收敛不可声明。
### 4.3 投影、投递、历史与参考数据
- **INV-23** 航班类消息(增量、删除、日计划)的 Redis 投影写成功才算处理完成。失败分两类:PG 事务提交前失败,事务整体回滚、消息保持未完成(`US-03` AC3);投影写失败发生在事务提交后,不回滚已提交的业务结果,保持未完成、下轮重做投影与后续步骤(`US-05` AC4)。两类都不置终态、不回填、不投递。
- **INV-24** Redis 航班投影只由本系统写入和移除;`GET /all/flights` 与网页客户端读同一份,返回当前全部动态航班(不含共享航班),不分页;Redis 异常时报错,不返回空列表伪装成功。
- **INV-25** 处理记录清理:只删「已有终态且已回填」并超过保留期的记录,未完成的不删,保留期可配置;未映射字段的记录不随处理记录到期清理(`US-05` AC3)。
- **INV-26** 静态参考数据按类别与编号保存,新消息覆盖旧记录;全量消息整体替换,增删改消息逐条处理;字段为空表示「当前没有值」,不是删除。
- **INV-27** 一类参考数据校验不通过就只停这一类,其他类照常;该类的已有记录不变。
- **INV-28** 航班只在历史写入确认成功后才从实时数据删除,删除前按 `D1` 必要时登记待发删除事件,历史存储未接通时一条也不删;写失败的下轮重来,已写入的不重复写入,单个航班失败不影响其他航班。与消息处理的互斥见 `INV-18`
### 4.4 已作废条款
- **INV-2** 水位与入队同事务:不允许出现「水位已推进、消息未入队」的持久化状态;水位只增不减,遇空洞即停,只有判定为永久空洞才放行,且放行只跳过空洞本身、不越过任何已存在的行。**[作废 by INV-2b]**
- **INV-4** 只领取已发现的行:主泵只领 `MSG_ID ≤ W`;水位之外的行只可能来自兼容入口,必须等水位追平后按序处理。**[作废 by INV-2b]**(水位取消,兼容入口写入的行即普通行。)
- **INV-5** 发现与处理互不阻塞:收报只看 `ID > W`,不以处理标记为谓词;终态而未回填的行不阻断后续消息的发现。**[作废 by INV-2b]**
- **INV-11** 自有 PG 的航班当前态是唯一权威;信箱、Kafka、展示视图都不是权威。**[作废 by INV-11b]**
- **INV-14** 报文未携带的字段不被隐式清空;集合按完整合并结果写入,保留输入顺序与源序号。**[作废 by INV-14b]**
- **INV-15** 缺席于某个日计划不构成删除理由;删除只由 FDEL 或受控历史清理触发。**[作废 by INV-15b]**
- **INV-17** 状态变更、待发事件、处理终态与回填意图在同一 PG 事务内原子提交。**[作废 by INV-17b]**
- **INV-20** 处理器幂等:同一消息重复执行只产生一次业务效果。身份唯一只防「重复记录」,不防「重新执行」;SIS 25 类与经 `Q8` 定案启用的 legacy 子类型完成逐类幂等矩阵前,本条**不可声明**(`G-FLOP-IDEMPOTENT`)。**[作废 by INV-20b]**
## 5. 声明边界
| 编号 | 承诺 | 依赖 | 现在能否作出 | 限制或原因 |
|---|---|---|---|---|
| CLM-3 | 失败重处理与重复发现不产生重复业务副作用 | `INV-20b` | 不能 | 逐类幂等规则未补齐(`G-FLOP-IDEMPOTENT` |
| CLM-4 | 信箱行最终都被写上处理标记 | `INV-7` | 不能 | 一直写不上的行留案并告警(`US-10` AC2 |
| CLM-6 | 单实例内按信箱编号升序的 FIFO 调度 | `PRE-5``INV-3` | 能 | 只声明按编号排序;「编号即到达顺序」依赖 `PRE-2``Q2`),未定案前不声明真实到达顺序 |
| CLM-7 | 主题 `msg` 上同一 `FLID` 内保序 | `INV-10``C-9``D2` | 不能 | 无按 `FLID` 的分区设计;`D2` 只保证单分区内生产顺序。跨 `FLID` 不承诺;不覆盖 `schd` |
| CLM-8 | 出站经 `COUTMSGS` | `C-4` | 能 | — |
| CLM-9 | 消息将在某个时限内完成处理 | — | 不能 | 处理标记的写入时刻不是完成时限:扫描周期、批次积压与单行重试都会延长实际延迟 |
| CLM-10 | 容量与吞吐量级 | — | 不能 | 无实测数据,取得信箱日量、峰值与单报文上限后重估 |
| CLM-11 | 配置不完整时拒绝启动;「双实例同时启动只允许一个处理」无系统侧机制承载 | `OPS-1``PRE-5` | 启动拒绝能;双实例验收不能 | 运行时跨实例互斥不在此版设计内——不引入并行主泵或分布式锁是非目标(requirements「范围与非目标」),单实例靠部署保证(`PRE-5`);达成方式待 `Q29` |
## 6. 待确认事项台账
### 6.1 待对方确认
| 编号 | 事项 | 当前假定 | 影响 |
|---|---|---|---|
| Q2 | 信箱编号的分配顺序、单调与不复用 | 见 `PRE-2``PRE-3` | 「编号即到达顺序」目前无法确认 |
| Q3 | 兼容入口的请求体上限、编码与 `Content-Type` 精确规则、HTTP 状态码、成功与失败响应结构 | 响应语义与解析限制已定(`C-7`);旧系统线索为共用 `ResponseDto`、成功 `body` 是信箱编号(接口契约「HTTP」) | 兼容入口无法验收 |
| Q4 | Kafka 载荷与去重标识 | 两个主题名、`msg` 单条变更、`schd` 定时批量已定(`US-08``C-9`)。无特别分区设计。`schd` 每条 record 装什么、批次边界未定 | `schd` 粒度及去重标识仍须确定 |
| Q7 | 处理时间列的列名、类型与可空性;信箱时钟基准与时区 | 处理标记即处理时间列;回填未完成前行须在,未完成消息原文须在(`C-1` | 列元数据与时钟基准未定 |
| Q8 | 现场会发但 SIS 未定义的子类型(靠桥、延误等)的报文形态与逐类终态 | 按现有处理逻辑延续(`US-05` AC1) | 逐类终态与幂等规则未定(`G-FLOP-SEMANTICS` |
| Q9 | 清除方案与保留期 | 本系统自行清理(`C-1`);旧系统按接收超过 1 天归档并删除入站行,是否沿用待确认 | 清除边界与保留期未定 |
| Q15 | 上游是否会以同一业务身份改发正文 | 假定不可变(`PRE-7` | 身份去重语义未定 |
| Q20 | Redis 投影的 key/value 结构、序列化方式与网页客户端读取约定 | 旧系统线索为 hash `flightInfo`、field 取 `FLID`(见接口契约「Redis:航班查询投影」) | 消费方读取契约无法定稿 |
| Q24 | `GET /all/flights` 的返回字段与类型、集合外层结构、状态码与错误响应 | 读 Redis 投影、返回当前全部动态航班、不分页(`C-11`);旧系统线索为非共享航班 `SCHD.FLTR` 列表(接口契约「HTTP」) | 查询契约无法定稿 |
| Q25 | `RQRD`/`RQFD` 的子类型清单、发送方取值、时间与序号的构造规则 | 出站只有这两类报文(架构「系统定位与范围」);旧系统线索为 `TYPE=RQFD``STYP=NONE``SNDR=OSH5`(接口契约「HTTP」) | 出站报文无法编码 |
答复就地更新结论,并按 [README.md](README.md)「维护清单」落到对应条款。
### 6.2 已确认
| 编号 | 事项 | 结论 |
|---|---|---|
| Q11 | 上游 `SEQN` 的重置周期与身份是否加日期边界 | 已定案:`SEQN` 自增,极少重置,重置后不与旧消息冲突,不加日期边界(`C-3` |
| Q13 | 日计划未携带字段的删除语义 | 见 `C-6` |
| Q14 | 主/共享删除顺序 | 已定案:标记删除,各自独立(`C-5` | 已闭环 |
### 6.3 本系统与需求方待决
以下事项不出自对接方,由本系统与需求方决定:
| 编号 | 事项 | 当前假定 | 影响 |
|---|---|---|---|
| Q1 | 生产库选型 | 自有 PG 是唯一权威;生产环境用 PostgreSQL 还是 Oracle 11g 不能从三份依据确定,Oracle 适配验证通过前不作支持承诺 | 生产部署验收 |
| Q17 | `POST /schd/sync` 的请求字段与时间格式、成功响应表示已登记还是已落信、状态码与错误响应 | 交付承诺止于落信(`C-4`);旧系统线索为 `{startDate, endDate}` 与 12 小时制时间(接口契约「HTTP」) | 响应契约无法定稿(`C-8` |
| Q18 | 人工发起 `RQRD` 的方式 | `US-09` 要求人工发起,HTTP 接口清单没有对应入口 | 参考数据请求无法人工触发 |
| Q19 | `msg` 的版本与去重标识是否直接采用航班当前态的版本号 | 可用依据是 `FLIGHT_SCHD` 的版本规则(`INV-13` | 消费方去重规则未定(与 `Q4` 衔接) |
| Q21 | 回退时在途消息(已提交业务变更、未到处理完成)的处置 | 回填了结后切换(`OPS-4``PRE-1`);在途消息无跨系统幂等保障 | 回退演练的验收口径(`OPS-4` |
| Q22 | 是否在自有 PG 留存入站原文副本,及原文提前清除时已登记消息的处置 | 不留存,原文只从信箱读取 | 提前清除的消息不可恢复,处置未定 |
| Q23 | 日计划中运营日冲突的处置 | 整包校验失败不落地(`INV-19`);冲突是否属于整包校验未定 | 冲突场景无法验收(`INV-12` |
| Q26 | `REF_MASTER` 的物理列、唯一键、空值存储与写入后可见时点 | 记录用类别码加识别标签识别(接口契约「静态参考数据类别与编号来源」) | admin-api 读取契约无法定稿(`C-10` |
| Q27 | Elasticsearch 历史索引、文档 ID、字段映射、成功判据、保留期与容量上限、写入结果不明的对账与幂等策略 | 历史写入确认成功才删实时数据(`D1``INV-28` | 历史链路无法验收(`US-14``G-FLIGHT-HIST-RETENTION` |
| Q28 | `REQ_TRACK` 已结案记录的保留期取值 | 到期清理没有可依据的窗口(`G-REQ-TRACK-RETENTION` | 请求历史清理无法实现(`US-09` |
| Q29 | 「双实例同时启动只允许一个处理」的达成方式 | 由部署规程保证单实例(`CLM-11`);是否需要系统侧启动互斥未决 | `OPS-1` 双实例验收不闭环 |
## 7. 当前已知偏差
本表是偏差标记的唯一出处,其他文档只写 `G-NAME`。闭合时删除本行与全仓引用。
| 偏差 | 缺什么,会怎样 | 影响 |
|---|---|---|
| `G-REQ-TRACK` | 出站请求没有跟踪:登记、编码、超时与应答匹配都没有实现 | `US-09` |
| `G-REQ-OPEN-UNIQUE` | 同一报文类型同时最多一条已落信、未结案请求的限制没有实现;待发送登记不算占用该名额 | `US-09` |
| `G-REQ-TRACK-RETENTION` | `REQ_TRACK` 已结案记录的保留期取值未定,到期清理作业没有可依据的窗口(取值待 `Q28` | `US-09` |
| `G-FLIGHT-HIST-RETENTION` | 历史存储的保留期与容量上限未定(取值待 `Q27` | `INV-28`;实时数据删除后历史是唯一副本 |
| `G-FLOP-IDEMPOTENT` | 逐类幂等规则未补齐 | `INV-20b``CLM-3` |
| `G-FLOP-SEMANTICS` | `STYP` 没有白名单,`ROUT` 未限制 4 条,运行状态落点与已删除航班的处理与 `US-05` 不符 | `US-05``INV-14b` |
| `G-FLOP-UNMAPPED` | [XSD](legacy/unisysaodbsis.xsd)「FLOP 元素」里有些字段没有解码或映射错了,会被静默丢掉 | `US-05` |
| `G-MAFL` | 主航班的共享航班列表未实现 | `INV-21` |
| `G-SRVT-VIPF` | `SRVT``VIPF` 两个集合没有落到持久化明细 | `US-05` |
| `G-SCAN-PREDICATE` | 收报仍按水位扫描,不是按「处理时间为空」读取 | `US-01``INV-2b` |
| `G-REDIS-PROJECTION` | Redis 投影没有写入与移除路径 | `US-05``US-06``US-07``US-12` |
| `G-SCHD-SNAPSHOT` | 日计划快照不删除缺席航班、不清除未携带字段,也没有分批;逐航班重写幂等未补齐 | `INV-15b``INV-17b``INV-31` |
| `G-PROC-CLEANUP` | 处理记录的到期清理作业未实现 | `US-11``INV-25` |
| `G-REF-DATA` | 静态参考数据没有处理,当前按「合法但不支持」跳过并回填;参考数据表与 admin-api 直读未落地 | `US-13``US-03` |
## 8. 验证映射
| 不变量 | 需求验收 | 要观察的结果 |
|---|---|---|
| INV-2b | `US-01` AC1/AC2/AC4 | 扫描重来与重启后登记数不变,行不丢 |
| INV-2b、C-7 | `US-02` AC1~AC5 | 兼容入口接受三种媒体类型、默认 UTF-8;空报文、超上限、非法 XML 不落信并返回错误,解析禁用外部实体与外部资源;成功返回编号且只表示落信;内网来源由网络层配置核对;写入的行与上游投递同路径被发现、登记 |
| INV-3 | `US-01` AC3、`US-03` AC1 | 队头未完成时,后面的消息不被处理;处理顺序为编号升序 |
| CLM-6、PRE-2 | `US-01` AC3 | 「编号即到达顺序」的到达顺序声称待 `PRE-2``Q2`)定案,当前只声明按编号排序(`CLM-6` |
| INV-30 | `US-03` AC2/AC5 | 死信与跳过留档且无业务副作用;错误在对应处理记录上可查 |
| INV-6、INV-16 | `US-03` AC3 | 失败回滚后消息仍在未完成;已提交结果不被副作用回滚 |
| INV-7、INV-8 | `US-10` AC1/AC2 | 标记只写一次;重启后继续,写不上的有记录与告警 |
| INV-9、PRE-7 | `US-01` AC2、`US-03` AC5 | 同一编号重复出现时处理记录数不增加;相同业务身份、不同编号的行先比对内容——一致跳过留档,不一致留档、告警、不产生业务效果,处置待 `Q15` |
| INV-10、C-9 | `US-08` AC1/AC2/AC3 | `msg` 单条变更、`schd` 批量;失败重试后仍能投出;一直失败的记录保留可查并告警;`FLID` 端到端保序不可声明(无分区设计,见 `CLM-7` |
| INV-11b | 架构「系统定位与范围」 | 航班当前态的权威写入只在自有 PG |
| INV-12、INV-13 | 架构「必须保持的约束」、`US-04` AC1 | 运营日写入后不变,没带计划时间的航班留空;重复消息不推进版本 |
| INV-14b | `US-04` AC2 | 未携带的字段保持原值 |
| INV-29 | `US-04` AC3 | 已删除航班收到 `ADFT` 后恢复有效并推进版本 |
| INV-15b | `US-07` AC2/AC3 | 缺席的航班在 PG 标为已删除并从 Redis 投影移除;未携带的字段被清空 |
| INV-17b | `US-03` AC4、`US-05` AC4、`US-06` AC1 | 投影写失败时,没有终态与回填意图落库;处理完成前事件不可投递 |
| INV-18 | `US-14` AC4 | 历史清理跳过正在被消息处理的航班 |
| INV-19 | `US-07` AC1 | 校验失败后本地数据与版本不变 |
| INV-31 | `US-07` AC4/AC5 | 分批失败后整包重处理收敛到同一目标(`G-SCHD-SNAPSHOT` 闭合前无法验证);Redis 在整包写入完成后按快照刷新,成功即与快照一致 |
| INV-20b、CLM-3 | `US-01` AC2、`US-03` AC3、`US-05` AC1/AC2 | 重复执行不增加业务效果;逐子类型规则与幂等矩阵在 `Q8``G-FLOP-IDEMPOTENT``G-FLOP-SEMANTICS` 闭合前无法验证 |
| INV-21、INV-22、INV-28 | `US-06` AC1/AC2、`US-14` AC3 | 航班标记删除后从投影移除;删除事件在实时数据删除前登记(`D1`),投递按至少一次随后完成;移除失败时下轮重做 |
| INV-23 | `US-05` AC4、`US-06` AC1 | 投影写失败的消息下轮仍被处理 |
| INV-24 | `US-12` AC1/AC2 | 返回全部非共享航班,且与 Redis 一致;Redis 故障时返回错误 |
| INV-25 | `US-11` AC1/AC2 | 未完成的记录不被删除 |
| INV-26、INV-27 | `US-13` AC1~AC5 | 全量消息整体替换、增删改消息逐条生效;字段空值保存为「当前没有值」而非删除;失败类别的已有记录不变;参考数据落独立数据表供 admin-api 只读(`C-10` |
| INV-28 | `US-14` AC1~AC4 | 按判史条件与定时选出候选;历史写入失败的航班仍在实时数据中,单个失败不影响其他 |
| CLM-4(留案告警) | `US-10` AC2 | 一直写不上的行有记录与告警 |
| CLM-8 | `US-09` AC1AC3 | 出站请求写入 `COUTMSGS` |
| CLM-9(不承诺完成时限) | `OPS-2` | 积压、处理失败、投递失败、回填失败各有指标与告警(架构「总体架构」) |
| CLM-10(容量假设) | 无对应运行验收 | 上线前用现场量级重估,取值见 [reference.md](reference.md)「参数注册表」 |
| OPS-4 | `OPS-4` | 回退演练:回填了结后切回,旧系统不重处理已产生业务效果的消息;在途窗口处置见 `Q21` |
| CLM-11(单实例防线) | `OPS-1` | 配置错误启动失败测试可验收;「双实例同时启动只允许一个处理」未闭环——系统无运行时互斥,达成方式待 `Q29` |
| PRE-9(测试隔离) | `OPS-3` | 测试环境配置核对:独立的数据库、Redis 与 Kafka 主题,不连接生产信箱 |