Files
msgexchange-v2/docs/specification.md
T
windyboy 2a06c42993 docs(acm2-75): 删除作废条款并收紧 CLM 与 Q 序号
- 删除 4.4 已作废条款(INV 旧编号已无外部引用)
- CLM-3,6,7,8,9,10,11 收紧为 CLM-1 至 CLM-7,全文引用同步更新
- 6.2 已确认事项按 Q 编号排序
- C-1/C-4/C-7/C-11 合并已确认结论,6.1 清空
2026-09-16 17:56:19 +08:00

199 lines
18 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-11`。 |
| 自有 PG | 本系统唯一的业务数据库;航班当前态、管道记录与静态参考数据都在这里。 |
| 权威 | 航班当前态以自有 PG 为准(`INV-5`)。 |
| 出站请求 | 经 `COUTMSGS` 发向 AODB 的 `RQRD` 参考数据请求与 `RQFD` 日计划请求,消费方为 CIIMS adapter。 |
| 运营航班显示界面 | 需求所称网页客户端:Kafka 侧称运营航班显示界面,查询侧称网页客户端(`GET /all/flights` / Redis)。 |
| 航班历史 | 已结束航班写入 Elasticsearch 后的副本;写成功后才从实时数据删除。 |
| 静态参考数据 | 13 类基础数据与资源状态,写自有 PG 的独立数据表,admin-api 直接只读。 |
## 2. 约定
### 2.1 共享信箱(库方)
- **C-1** 本系统清理已处理的入站信箱行(MySQL `CMINMSGS`):回填完成且超过保留期后才删;保留期可配置,按约 1 个月(`Q9`)。处理未完成或回填未完成的行不删。
- **C-2** 共享 MySQL 不做 Schema 变更,本系统只读写 `CMINMSGS``COUTMSGS` 两张表。
### 2.2 上游(AODB / SIS
- **C-3** 业务身份由 `SNDR``TYPE``STYP``SEQN` 四字段组合;`SEQN` 自增,极少重置(消息服务器重启),重置后不会与旧消息冲突。
- **C-4** 出站请求写入 `COUTMSGS`;交付承诺止于落信。编码:`SNDR=OMMS``SEQN` 本系统自建序列;`DTTM` 北京时间 `YYYYMMDDHHMMSS``RQRD` 子类型以 SIS 为准共 14 类;`RQFD``STYP=NONE`,全量同步不带 `STDB`/`STDE` 等筛选(`Q25`)。
- **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` 与网页客户端读同一份;返回 JSON 由消息文档中的 XML 结构转换而来(`Q20``Q24`)。
## 3. 前提
前提失效时不变量必须整体重估。
| 编号 | 前提 | 若不成立的影响 | 状态 |
|---|---|---|---|
| PRE-1 | 测试环境与生产隔离:独立的数据库、Redis 与 Kafka 主题,不连接生产信箱 | 测试结论与隔离验收(`OPS-3`)失效 | 部署与配置约束 |
## 4. 不变量
### 4.1 管道
- **INV-1** 处理时间仍为空的信箱行会登记到本地;同一编号只登记一次。重扫或重启不会重复登记,也不会漏掉未登记的行。
- **INV-2** 只有本地处理结束后,才写信箱里的处理时间;本地记「已结束」时,必须同时记下还要去更新信箱,两笔记在同一次写入里。
- **INV-3** 航班增量与删除:改状态和记「待发 Kafka」同一次写入;记「已结束」和「还要更新信箱」另一次写入,且须在 Redis 写成功之后。处理未结束前不发 Kafka(`US-03` AC4)。日计划与静态参考数据见架构「主流程」。
- **INV-4** 日计划整份报文校验不过时,本地航班数据一律不改(`US-07` AC1)。
### 4.2 航班域
- **INV-5** 航班当前态只以自有 PG 为准;信箱、Redis、Kafka、展示视图都不是。
- **INV-6** `FLID` 唯一。
- **INV-7** 日计划:快照里没有的航班标记删除、登记删除事件并从 Redis 去掉;报文没带的字段本地清掉(`US-07` AC2/AC3)。
- **INV-8** 航班标成已删除后,要从 Redis 去掉;去掉成功才算这条消息处理完(`US-06` AC1)。
- **INV-9** 日计划可以分批写库,但整份写完并且 Redis 按这份结果刷完,才算处理完;失败就整份重来(`US-07` AC4/AC5)。
### 4.3 Redis 投影
- **INV-10** Redis 写成功,这条消息才算处理完;写失败就还没处理完,不回填、不发 Kafka,下轮再写(`US-05` AC4)。本地已经写进库的,不因为 Redis 失败而撤掉(`US-03` AC3)。
- **INV-11** Redis 航班投影只由本系统维护;查询与网页客户端读同一份;Redis 异常时报错,不交空列表(`US-12`)。
## 5. 声明边界
| 编号 | 承诺 | 依赖 | 现在能否作出 | 限制或原因 |
|---|---|---|---|---|
| CLM-1 | 同一消息再处理不会多出一份业务效果 | `US-03` | 不能 | 各类报文的细则未补齐(`G-FLOP-IDEMPOTENT` |
| CLM-2 | 按信箱编号升序处理 | `US-03` AC1 | 能 | — |
| CLM-3 | 主题 `msg` 上同一 `FLID` 内按发送顺序保序 | `US-08` AC2、`C-9` | 能 | `msg` 单分区;至少一次重发时消费者仍可能见到乱序 |
| CLM-4 | 出站请求写入共享出站表 `COUTMSGS` | `C-4` | 能 | 只保证写入信箱,不保证 AODB 收到 |
| CLM-5 | 消息在固定时限内处理完 | — | 不能 | 需求未定完成时限;现场一般为即时处理,但不作时限保证 |
| CLM-6 | 容量与吞吐量级 | — | 不能 | 现场量级暂无;有日量、峰值等数据后再估 |
| CLM-7 | 配置不完整时拒绝启动 | `OPS-1` | 能 | — |
## 6. 待确认事项台账
### 6.1 待对方确认
(无)
答复就地更新结论,并按 [README.md](README.md)「维护清单」落到对应条款。
### 6.2 已确认
| 编号 | 事项 | 结论 |
|---|---|---|
| Q2 | 信箱编号的单调、不复用、不回退 | 已定案:编号即入库行号,单调递增、不复用、不回退;按编号升序处理即按到达顺序(`US-01` AC3、`CLM-2` |
| Q4 | `schd` 载荷 | 已定案:`schd` 每条为运营航班 JSON`C-9``US-08` |
| Q7 | 入站处理时间列 | 已定案:与旧系统相同,列名为 `CMINMSGS_DATE_PROCESSED`;空为未处理,回填写入完成时刻(`US-10` |
| Q8 | 现场有、文档没有的报文 | 已定案:仍须想办法处理,不得因 SIS 未记载就丢掉(`US-05` AC1);具体形态与落库规则随对拍补齐 |
| Q9 | 入站信箱行(MySQL `CMINMSGS`)清除 | 已定案:本系统回填后自清(`C-1`);保留期可配置,按约 1 个月 |
| Q11 | 上游 `SEQN` 的重置周期与身份是否加日期边界 | 已定案:`SEQN` 自增,极少重置,重置后不与旧消息冲突,不加日期边界(`C-3` |
| Q13 | 日计划未携带字段的删除语义 | 见 `C-6` |
| Q14 | 主/共享删除顺序 | 已定案:标记删除,各自独立(`C-5` |
| Q20 | Redis 投影用途 | 已定案:供读取全体动态航班;与 `GET /all/flights`、网页客户端同一份(`C-11``US-12` |
| Q24 | `GET /all/flights` 返回体结构 | 已定案:JSON 由消息文档中的 XML 结构转换而来;读 Redis、返回全体动态航班、不分页(`C-11``US-12` |
| Q25 | `RQRD` / `RQFD` 编码字段 | 已定案:`SNDR=OMMS``SEQN` 本系统自建序列;`DTTM` 为北京时间 `YYYYMMDDHHMMSS`SIS META);`RQRD` 子类型以 SIS 为准共 14 类(含 `RSTA`,其可选 `RTYP`);`RQFD``STYP=NONE``STDB`/`STDE` 等筛选可选,全量同步不带筛选(SIS:无参数则返回当天全部,对齐 `US-07`)(`C-4` |
### 6.3 本系统与需求方待决
以下事项不出自对接方,由本系统与需求方决定:
| 编号 | 事项 | 当前假定 | 影响 |
|---|---|---|---|
| Q1 | 生产库选型 | 自有 PG 是唯一权威;生产环境用 PostgreSQL 还是 Oracle 11g 不能从三份依据确定,Oracle 适配验证通过前不作支持承诺 | 生产部署验收 |
| Q3 | `POST /cminmsgs/send` 的长度上限与失败响应 | 仅内部联调、无外部引用;成功返回编号等行为见 `C-7`;上限与失败格式现阶段不定,实现时在代码里自定 | 不阻塞对外契约 |
| Q17 | `POST /schd/sync` 的请求字段与时间格式、成功响应表示已登记还是已落信、状态码与错误响应 | 交付承诺止于落信(`C-4`);旧系统线索为 `{startDate, endDate}` 与 12 小时制时间(接口契约「HTTP」) | 响应契约无法定稿(`C-8` |
| Q18 | 人工发起 `RQRD` 的方式 | `US-09` 要求人工发起,HTTP 接口清单没有对应入口 | 参考数据请求无法人工触发 |
| Q21 | 回退时在途消息(已提交业务变更、未到处理完成)的处置 | 回填了结后切换(`OPS-4`);在途消息无跨系统幂等保障 | 回退演练的验收口径(`OPS-4` |
| Q22 | 是否在自有 PG 留存入站原文副本,及原文提前清除时已登记消息的处置 | 不留存,原文只从信箱读取 | 提前清除的消息不可恢复,处置未定 |
| Q23 | 日计划中运营日冲突的处置 | 未定 | 冲突场景无法验收 |
| Q26 | `REF_MASTER` 的物理列、唯一键、空值存储与写入后可见时点 | 记录用类别码加识别标签识别(接口契约「静态参考数据类别与编号来源」) | admin-api 读取契约无法定稿(`C-10` |
| Q27 | Elasticsearch 历史索引、文档 ID、字段映射、成功判据、保留期与容量上限、写入结果不明的对账与幂等策略 | 历史写入确认成功才删实时数据(`D1``US-14` AC3 | 历史链路无法验收(`US-14``G-FLIGHT-HIST-RETENTION` |
| Q28 | `REQ_TRACK` 已结案记录的保留期取值 | 到期清理没有可依据的窗口(`G-REQ-TRACK-RETENTION` | 请求历史清理无法实现(`US-09` |
## 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` | `US-14`;实时数据删除后历史是唯一副本 |
| `G-FLOP-IDEMPOTENT` | 逐类幂等规则未补齐 | `US-03``CLM-1` |
| `G-FLOP-SEMANTICS` | `STYP` 没有白名单,`ROUT` 未限制 4 条,运行状态落点与已删除航班的处理与 `US-05` 不符 | `US-05` |
| `G-FLOP-UNMAPPED` | [XSD](legacy/unisysaodbsis.xsd)「FLOP 元素」里有些字段没有解码或映射错了,会被静默丢掉 | `US-05` |
| `G-MAFL` | 主航班的共享航班列表未实现 | `US-06` AC2`C-5` |
| `G-SRVT-VIPF` | `SRVT``VIPF` 两个集合没有落到持久化明细 | `US-05` |
| `G-SCAN-PREDICATE` | 收报仍按水位扫描,不是按「处理时间为空」读取 | `US-01``INV-1` |
| `G-REDIS-PROJECTION` | Redis 投影没有写入与移除路径 | `US-05``US-06``US-07``US-12` |
| `G-SCHD-SNAPSHOT` | 日计划快照不删除缺席航班、不清除未携带字段,也没有分批;逐航班重写幂等未补齐 | `INV-7``INV-3``INV-9` |
| `G-PROC-CLEANUP` | 处理记录的到期清理作业未实现 | `US-11` |
| `G-REF-DATA` | 静态参考数据没有处理,当前按「合法但不支持」跳过并回填;参考数据表与 admin-api 直读未落地 | `US-13``US-03` |
## 8. 验证映射
| 不变量 | 需求验收 | 要观察的结果 |
|---|---|---|
| INV-1 | `US-01` AC1/AC2/AC4 | 扫描重来与重启后登记数不变、行不丢;同一编号重复出现时处理记录数不增加 |
| INV-1、C-7 | `US-02` AC1~AC5 | 兼容入口接受三种媒体类型、默认 UTF-8;空报文、超上限、非法 XML 不落信并返回错误,解析禁用外部实体与外部资源;成功返回编号且只表示落信;内网来源由网络层配置核对;写入的行与上游投递同路径被发现、登记 |
| CLM-2 | `US-01` AC3、`US-03` AC1 | 按编号升序处理;队头未完成时后面的消息不被处理 |
| US-03 AC2/AC5 | `US-03` AC2/AC5 | 死信与跳过留档且无业务副作用;错误在对应处理记录上可查 |
| US-03 AC3 | `US-03` AC3 | 失败回滚后消息仍在未完成;已提交结果不被写信箱处理时间或发 Kafka 失败回滚 |
| INV-2 | `US-10` AC1/AC2 | 终态后才回填;重启后继续,写不上的有记录与告警 |
| C-9 | `US-08` AC1/AC2/AC3 | `msg` 单条变更、`schd` 批量;失败重试后仍能投出;一直失败的记录保留可查并告警;`msg` 同一 `FLID` 按发送顺序保序(`CLM-3`);同一条可能多发(`C-9` |
| INV-5 | 架构「系统定位与范围」 | 航班当前态的权威写入只在自有 PG |
| INV-6 | 架构「必须保持的约束」 | `FLID` 唯一 |
| US-04 AC2 | `US-04` AC2 | 未携带的字段保持原值 |
| INV-7 | `US-07` AC2/AC3 | 缺席的航班在 PG 标为已删除并从 Redis 投影移除;未携带的字段被清空 |
| INV-3 | `US-03` AC4、`US-05` AC4、`US-06` AC1 | 投影写失败时,没有终态与回填意图落库;处理完成前事件不可投递 |
| US-14 AC4 | `US-14` AC4 | 历史清理跳过正在被消息处理的航班 |
| INV-4 | `US-07` AC1 | 校验失败后本地数据与版本不变 |
| INV-9 | `US-07` AC4/AC5 | 分批失败后整包重处理收敛到同一目标(`G-SCHD-SNAPSHOT` 闭合前无法验证);Redis 在整包写入完成后按快照刷新,成功即与快照一致 |
| CLM-1 | `US-03` | 同一消息不产生两次效果;逐子类型规则与幂等矩阵在 `Q8``G-FLOP-IDEMPOTENT``G-FLOP-SEMANTICS` 闭合前无法验证 |
| INV-8 | `US-06` AC1 | 航班标记删除后从投影移除;移除失败时下轮重做 |
| US-14、D1 | `US-14` AC3 | 历史写入成功才删实时数据;删除事件在实时数据删除前登记(`D1` |
| US-06 AC2 | `US-06` AC2 | 删共享联动主航班;删主航班级联删共享 |
| INV-10 | `US-05` AC4、`US-06` AC1 | 投影写失败的消息下轮仍被处理 |
| INV-11 | `US-12` AC1/AC2 | 返回全部非共享航班,且与 Redis 一致;Redis 故障时返回错误 |
| US-11 | `US-11` AC1/AC2 | 未完成的记录不被删除 |
| US-13 | `US-13` AC1~AC5 | 全量整体替换、增删改逐条;空值是「没有值」不是删除;一类校验失败只停该类;参考数据落独立表供 admin-api 只读(`C-10` |
| US-10 AC2 | `US-10` AC2 | 写失败重试与告警可观测 |
| CLM-4 | `US-09` AC1AC3 | 出站请求写入 `COUTMSGS` |
| CLM-5(不承诺完成时限) | — | 需求未定完成时限;现场一般为即时处理 |
| CLM-6(容量) | — | 现场量级暂无;有数据后再估 |
| OPS-4 | `OPS-4` | 回退演练:回填了结后切回,旧系统不重处理已产生业务效果的消息;在途窗口处置见 `Q21` |
| CLM-7 | `OPS-1` | 配置错误启动失败测试可验收 |
| PRE-1(测试隔离) | `OPS-3` | 测试环境配置核对:独立的数据库、Redis 与 Kafka 主题,不连接生产信箱 |