Files
msgexchange-v2/docs/specification.md
T

280 lines
35 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` 只在本文件定义;ID 语法见 [README.md](README.md)。
约定条目的标记:
- 需要对方确认的,末尾标 `(待确认 Qn`
- 内容已定、个别字段未定的,另起一行以「待确认:」列出并指向 `Qn`
- 本系统单方遵守、不依赖对方认可的,末尾标 `(本系统单方承诺)`
- 未标注的,表示需求或架构已定,本系统按此执行。
作废条款集中放在各节末尾,保留原文与作废标记。
## 1. 术语
| 术语 | 含义 |
|---|---|
| 上游 | 产生报文的 AODB,报文经 CIIMS adapter 写入信箱。 |
| 信箱 | 共享 MySQL 的 `CMINMSGS`(入站)与 `COUTMSGS`(出站),归库方所有;边界见 `C-14`。 |
| 库方 | 信箱所在的共享 MySQL 管理方,即 CIIMS adapter 方。 |
| 处理标记 | 即信箱行上的处理时间:为空表示未处理,处理完成时写入完成时刻;写规则见 `C-15`。 |
| 落信 | 报文写入信箱成为一行;入站由 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-3** 信箱编号不复位、不复用、不回退,含表轮换、备份恢复与自增归零。不丢消息依赖这条(`PRE-2``PRE-3`)。`(待确认 Q2`
- **C-4** 报文行不可变:同一业务身份(`SNDR``TYPE``STYP``SEQN`)的重发是同一内容。`(待确认 Q15`
- **C-5** 处理标记即处理时间列:本系统只写完成时刻、只填空值(`C-15`),不在该列引入状态码等其它语义;死信、跳过与回填失败的原因记在自有 PG。
待确认:处理时间列的列名、类型与可空性(`Q7`)。
- **C-6** 原文的保留期与清除时机由库方定;本系统不承诺清除时间,只要求不早于 `C-7` 的下界。`(待确认 Q7、Q9`
- **C-7** 保留期下界分两层:回填重试期间信箱行必须仍在、标记列仍为空——`US-10` AC2 的重试需要的是可更新的行,不是原文;处理未完成的消息原文必须仍在——下轮重处理(`US-03` AC3)以原文为依据。`(待确认 Q7、Q9`
- **C-8** 清除由库方执行;本系统不执行 DDL、不清数据、不写共享历史表(`C-14`)。清除是否需要标记以外的证据,另行确认。`(待确认 Q9`
- **C-9** 清除的方案与 DDL 授权由库方定,本系统不参与选型。`(待确认 Q9`
- **C-10** 信箱时间列由写入方写入,其时钟基准须可解释(`PRE-4`)。
待确认:时区与允许偏斜(`Q7`)。
- **C-12** 原文被提前清除时,本系统不补造原文,也不把这类消息当成功。已登记的消息无法解码,也不能按 `US-03` AC2 判为非法——原文不可得不等于报文非法;未定前按处理失败保持未完成并告警(`US-03` AC3),队头因此阻塞是显式接受的代价,处置口径待 `Q22` 定案。信箱行在登记前整行消失时,扫描谓词对该行不可见,本系统无法发现其存在;防线只剩 `C-7` 的保留期下界由库方遵守(`Q9`)。`(本系统单方承诺)`
- **C-14** 本系统不建表、不改表结构、不迁移 schema、不清数据,也不写共享历史表。
- **C-15** 处理标记只在空值上写入处理完成时刻,写完不回撤、不覆盖已有值。`(本系统单方承诺)`
- **C-16** 回填失败的行保留记录并告警,记录在对应信箱行被清除前保持可查。`(本系统单方承诺)`
- **C-30** 本系统读取入站信箱 `CMINMSGS` 不加锁、不阻塞写入方,读取谓词、顺序与批量以 `INV-2b` 为准;除回填处理标记(`C-15`)与兼容入口落信(`C-28`)外不写 `CMINMSGS``COUTMSGS` 的写入见 `C-24`
- **C-34** 切换与回退以信箱处理标记交接(`OPS-4``PRE-1`):切回旧系统前,「已终态但未回填」的行必须清零——每条终态行的处理标记都已写上才算交接完成。放弃自动重试的行标记仍为空(放弃不等于标记已确认),本系统没有任何能阻止旧系统消费它的可观察状态(`C-15` 只填空值、不覆盖):必须先人工恢复重试至打标,或与库方另行定处置(`Q9`);否则这些行切回后会被旧系统再处理。已登记、未到处理完成的消息同样没有交接状态。
待确认:在途消息的回退处置(`Q21`)。
### 2.2 上游(AODB / SIS
- **C-20** 业务身份由 `SNDR``TYPE``STYP``SEQN` 组成,语义由上游定义,取值范围与回绕以 [SIS 接口规范](legacy/SIS_AODB_RMS-V0.1.md) 为准;`SEQN` 的重置周期未知,它决定身份是否加入日期边界。`(待确认 Q11`
- **C-21** `FLID` 在保留期内不复用;复用会让「只进不退」的合并把新航班的事件压掉。`(待确认 Q16`
- **C-23** 应答到达时按报文类型对应到等待中的请求;AODB 发错或迟到的应答不更新数据,记录后跳过(`US-09` AC2)。`SCHD-RESP` 只在请求未过期时生效,迟到的应答不更新数据(`US-07`)。
待确认:用哪些字段对应、超时如何判定(`Q5`)。
- **C-24** 出站信箱 `COUTMSGS`:消费方是 CIIMS adapter。`RQRD``RQFD` 各自同时最多一条已落信、未结案的请求;同一子类型发新请求时旧请求作废,新请求登记为待发送,等该报文类型的在途请求收到应答、失败或超时后再落信;请求超过时限未等到应答标记超时(`US-09` AC1)。收到 `EROR` 时定位到本系统发出的请求,标记失败并告警(`US-09` AC3)。重试只针对仍有效且确认未落信的请求;写入结果不明时记录并告警,不直接重发;交付承诺只到落信(架构「主流程」)。结案只有三种:应答到达且数据处理成功、超时、`EROR` 失败;未结案的在途请求占住同类的落信名额。
待确认:ACK 与错误列的语义及写入责任、出站行的清除与保留期、重复落信的识别规则、作废请求的范围(未落信直接撤销,已落信的如何结案)及其应答是否仍更新数据、写入结果不明的请求如何释放名额(`Q10`)。
- **C-25** 删除主航班时级联删除其共享航班,原子提交、不删一半(`US-06` AC2)。本系统不向 AODB 回发 `EROR`:出站只有 `RQRD``RQFD`(架构「系统定位与范围」)。这是对 `SIS:1.6.5` 的正式例外——SIS 要求共享航班先删、主航班后删,顺序错乱时 RMS 向 AODB 回发 `EROR`;本系统级联删除不依赖该顺序,异常经告警暴露(`Q14`)。
- **C-26** 日计划快照里没有携带的字段视为 AODB 已删除该值,本地同步清除(`US-07` AC3)。
- **C-27** 五类资源分配报文(柜台 `CKDT`、转盘 `CLDT`、滑槽 `CHDT`、登机门 `GTDT`、机位 `PSDT``SIS:3.24``SIS:3.25``SIS:3.26``SIS:3.34``SIS:3.38`)在 SIS 中方向为 RMS→AODB,且标注 AODB 发来时 RMS 拒收;现场已定案照常接收处理(`US-05` AC3),这是对 SIS 的正式例外,与 AODB 的核对确认是实施前提。
### 2.3 HTTP 入口
- **C-28** `POST /cminmsgs/send` 的响应只表示接收结果:成功返回信箱编号,失败不返回编号;媒体类型支持 `text/xml``application/xml``text/plain`,默认 UTF-8;空报文、超过大小上限与非法 XML 不落信;解析禁用外部实体与外部资源访问;仅限内网,来源由网络层限制。
待确认:请求体上限取值与失败响应样例(`Q3`)。
- **C-33** `POST /schd/sync` 触发一次 `RQFD` 日计划请求;成功响应无论表示已登记还是已落信,都不代表 AODB 已收到,交付承诺止于落信(`C-24`)。
待确认:成功响应表示已登记还是已落信(`Q17`)。
### 2.4 下游(admin-api 与运营航班显示界面)
- **C-29** 对外投递按至少一次设计,不承诺端到端恰好一次:应用重启与待发事件重发都可能让同一条消息多发一次。主题 `msg` 上同一 `FLID` 的变更保序,跨 `FLID` 不承诺顺序;`schd` 不在本条保序范围内。
待确认:Kafka key 与分区规则(`Q4`)。
- **C-31** admin-api 直接读取本系统写入的静态参考数据表;本系统不调用 admin-api,也不从它拉取、补全或合并数据。
- **C-32** Redis 航班投影对消费方的读取口径以 `INV-24` 为准。
待确认:投影 key/value 结构与网页客户端读取约定(`Q20`)。
### 2.5 已作废条款
- **C-1** ID 单调:信箱 ID 按提交顺序分配,已发布水位之下不再出现更小的新 ID。`[待确认 Q2]` **[作废 by C-30]**
- **C-2** ID 分配 → 事务可见时延上界由库方**直接给出**。该值决定空洞老化阈值;**不可由 SIS 报文 `Expiry` 推导**`Expiry` 是报文保留与传输恢复口径,与「ID 分配后多久对读事务可见」不是同一个量)。**[作废 by C-30]**
- **C-11** 原文保留期是否沿用旧系统的 1 天窗口待确认;无论取何值都必须满足 `C-7` 的下界。`(待确认 Q9` **[作废 by C-6]**
- **C-13** 只读约定区间的信箱行(`ID > W`),单活动实例运行,不引入并行消费者。`[我们单方承诺]` **[作废 by C-30]**
- **C-22** 报文不可变,见 `C-4``(待确认 Q15` **[作废 by C-4]**
## 3. 前提
前提失效时不变量必须整体重估。
| 编号 | 前提 | 若不成立的影响 | 状态 |
|---|---|---|---|
| PRE-1 | 信箱消费权排他:同一时刻只有一个系统有权处理、打标与判定可清除 | 采集谓词、身份去重与清除前提全部失效 | 由切流规程保证,上线前另立 |
| PRE-2 | 信箱编号的分配顺序即到达顺序 | 「编号即到达顺序」的顺序声称失去依据 | 待确认 `Q2` |
| PRE-3 | 信箱编号空间不复位、不复用、不回退 | 同一编号可能重复登记 | 待确认 `Q2` |
| PRE-4 | 信箱时间列的时钟基准可解释,偏斜有界 | 与本地时间的比较会提前或推迟判定 | 待确认 `Q7` |
| PRE-5 | 单活动实例运行,信箱读取不加锁 | 并行读会让「已处理」判定互相踩踏 | 部署约束 |
| PRE-6 | 信箱与自有 PG 之间没有跨库事务 | 回填与清除都不能声称原子 | 架构事实 |
| PRE-7 | 报文不可变:同一业务身份的重发是同一内容 | 上游改发正文会被判为重复并静默跳过 | 待确认 `Q15` |
| PRE-8 | `FLID` 在保留期内不复用(见 `C-21`) | 「只进不退」的合并可能压掉新航班事件,旧的删除标记可能删掉在用航班 | 待确认 `Q16` |
| 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 投递失败可重试,不回滚已提交的本地业务结果;出站请求写入结果不明时记录告警、不直接重发(`C-24`)。
- **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)。
- **INV-22** 主航班与共享航班的删除在同一 PG 事务内提交。被删除的航班从 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``C-15``C-16` | 不能 | 一直写不上的行留案并告警(`US-10` AC2 |
| CLM-6 | 单实例内按信箱编号升序的 FIFO 调度 | `PRE-5``INV-3` | 能 | 只声明按编号排序;「编号即到达顺序」依赖 `PRE-2``Q2`),未定案前不声明真实到达顺序 |
| CLM-7 | 主题 `msg` 上同一 `FLID` 内保序 | `INV-10``C-29``D2` | 不能 | `D2` 只保证单分区内生产顺序;同一 `FLID` 落同一分区依赖按 `FLID` 作 key 的分区规则(`Q4`)。跨 `FLID` 不承诺;不覆盖 `schd` |
| CLM-8 | 出站交付承诺只到落信 | `C-24` | 能 | 只覆盖落信;ACK 与错误列语义未确认(`Q10` |
| CLM-9 | 消息将在某个时限内完成处理 | — | 不能 | 处理标记的写入时刻不是完成时限:扫描周期、批次积压与单行重试都会延长实际延迟 |
| CLM-10 | 容量与吞吐量级 | — | 不能 | 无实测数据,取得信箱日量、峰值与单报文上限后重估 |
| CLM-11 | 配置不完整时拒绝启动;「双实例同时启动只允许一个处理」无系统侧机制承载 | `OPS-1``PRE-5` | 启动拒绝能;双实例验收不能 | 运行时跨实例互斥不在此版设计内——不引入并行主泵或分布式锁是非目标(requirements「范围与非目标」),单实例靠部署保证(`PRE-5`);达成方式待 `Q29` |
## 6. 待确认事项台账
### 6.1 待对方确认
| 编号 | 事项 | 当前假定 | 影响 |
|---|---|---|---|
| Q2 | 信箱编号的分配顺序、单调与不复用 | 见 `C-3``PRE-2``PRE-3` | 「编号即到达顺序」目前无法确认 |
| Q3 | 兼容入口的请求体上限、编码与 `Content-Type` 精确规则、HTTP 状态码、成功与失败响应结构 | 响应语义与解析限制已定(`C-28`);旧系统线索为共用 `ResponseDto`、成功 `body` 是信箱编号(接口契约「HTTP」) | 兼容入口无法验收 |
| Q4 | Kafka 载荷与去重标识 | 两个主题名、`msg` 单条变更、`schd` 定时批量已定(`US-08`;接口契约「Kafka」);`msg``FLID` 保序见 `C-29``schd` 每条 record 装什么、批次边界未定 | key、分区规则、`schd` 粒度及去重标识仍须确定 |
| Q5 | 请求与应答的对应字段、超时判定 | 见 `C-23` | 请求跟踪无法闭环 |
| Q7 | 处理标记的允许值、原文保留期、处理时间列、信箱时钟基准与时区 | 只填空值,不回撤不覆盖(`C-15`);回填重试期间信箱行须在,未完成消息原文须在(`C-7`) | 允许值、保留期取值与时钟基准未定 |
| Q8 | 现场会发但 SIS 未定义的子类型(靠桥、延误等)的报文形态与逐类终态 | 按现有处理逻辑延续(`US-05` AC1) | 逐类终态与幂等规则未定(`G-FLOP-SEMANTICS` |
| Q9 | 清除方案与保留期 | 清除由库方执行(`C-8`);旧系统按接收超过 1 天归档并删除入站行,是否沿用待确认。见 `C-6``C-9` | 清除边界与保留期未定 |
| Q10 | 出站 ACK 与错误列语义、出站行清理与重复落信识别、作废请求的结案与应答处置、写入结果不明时名额的释放 | 交付承诺止于落信(`C-24`) | 出站行清理、去重责任与作废语义未定 |
| Q11 | 上游 `SEQN` 的重置周期与身份是否加日期边界 | 暂不加日期边界 | 身份算法不能定稿 |
| Q15 | 上游是否会以同一业务身份改发正文 | 假定不可变(`PRE-7` | 身份去重语义未定 |
| Q16 | `FLID` 的重用语义 | 假定保留期内不复用(`C-21` | 事件合并与删除标记未定 |
| Q20 | Redis 投影的 key/value 结构、序列化方式与网页客户端读取约定 | 旧系统线索为 hash `flightInfo`、field 取 `FLID`(见接口契约「Redis:航班查询投影」) | 消费方读取契约无法定稿 |
| Q24 | `GET /all/flights` 的返回字段与类型、集合外层结构、状态码与错误响应 | 读 Redis 投影、返回当前全部动态航班、不分页(`C-32`);旧系统线索为非共享航班 `SCHD.FLTR` 列表(接口契约「HTTP」) | 查询契约无法定稿 |
| Q25 | `RQRD`/`RQFD` 的子类型清单、发送方取值、时间与序号的构造规则 | 出站只有这两类报文(架构「系统定位与范围」);旧系统线索为 `TYPE=RQFD``STYP=NONE``SNDR=OSH5`(接口契约「HTTP」) | 出站报文无法编码(`C-24` |
答复就地更新结论,并按 [README.md](README.md)「维护清单」落到对应条款。
### 6.2 已确认
| 编号 | 事项 | 结论 |
|---|---|---|
| Q13 | 日计划未携带字段的删除语义 | 见 `C-26` |
| Q14 | 主/共享删除顺序与 EROR 回报义务 | 见 `C-25` |
### 6.3 本系统与需求方待决
以下事项不出自对接方,由本系统与需求方决定:
| 编号 | 事项 | 当前假定 | 影响 |
|---|---|---|---|
| Q1 | 生产库选型 | 自有 PG 是唯一权威;生产环境用 PostgreSQL 还是 Oracle 11g 不能从三份依据确定,Oracle 适配验证通过前不作支持承诺 | 生产部署验收 |
| Q17 | `POST /schd/sync` 的请求字段与时间格式、成功响应表示已登记还是已落信、状态码与错误响应 | 交付承诺止于落信(`C-24`);旧系统线索为 `{startDate, endDate}` 与 12 小时制时间(接口契约「HTTP」) | 响应契约无法定稿(`C-33` |
| Q18 | 人工发起 `RQRD` 的方式 | `US-09` 要求人工发起,HTTP 接口清单没有对应入口 | 参考数据请求无法人工触发 |
| Q19 | `msg` 的版本与去重标识是否直接采用航班当前态的版本号 | 可用依据是 `FLIGHT_SCHD` 的版本规则(`INV-13` | 消费方去重规则未定(与 `Q4` 衔接) |
| Q21 | 回退时在途消息(已提交业务变更、未到处理完成)的处置 | 回填了结后切换(`C-34`);在途消息无跨系统幂等保障 | 回退演练的验收口径(`OPS-4` |
| Q22 | 是否在自有 PG 留存入站原文副本,及原文提前清除时已登记消息的处置(含队头是否放行) | 不留存,原文只从信箱读取;提前清除的消息按处理失败保持未完成并告警(`C-12`) | 提前清除的消息不可恢复,处置未定 |
| Q23 | 日计划中运营日冲突的处置 | 整包校验失败不落地(`INV-19`);冲突是否属于整包校验未定 | 冲突场景无法验收(`INV-12` |
| Q26 | `REF_MASTER` 的物理列、唯一键、空值存储与写入后可见时点 | 记录用类别码加识别标签识别(接口契约「静态参考数据类别与编号来源」) | admin-api 读取契约无法定稿(`C-31` |
| 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-RESP-GUARD` | `SCHD-RESP` 没有过期判断,晚到的应答也会更新本地数据 | `US-07``C-23` |
| `G-REQ-TRACK` | 出站请求没有跟踪:登记、编码、超时与应答匹配都没有实现 | `US-09``C-24` |
| `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``INV-22` |
| `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-28 | `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-29 | `US-08` AC1/AC2/AC3 | `msg` 单条变更、`schd` 批量;失败重试后仍能投出且同一 `FLID` 顺序不颠倒(端到端保序待 `Q4`,见 `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-31` |
| INV-28 | `US-14` AC1~AC4 | 按判史条件与定时选出候选;历史写入失败的航班仍在实时数据中,单个失败不影响其他 |
| CLM-4(留案告警) | `US-10` AC2 | 一直写不上的行有记录与告警 |
| CLM-8(止于落信) | `US-09` AC1~AC3 | 请求落信即交付、写入结果不明不重发;在途唯一、超时与 `EROR` 定位告警待 `G-REQ-TRACK``G-REQ-OPEN-UNIQUE` 闭合后验证,匹配依据见 `Q5` |
| CLM-9(不承诺完成时限) | `OPS-2` | 积压、处理失败、投递失败、回填失败各有指标与告警(架构「总体架构」) |
| CLM-10(容量假设) | 无对应运行验收 | 上线前用现场量级重估,取值见 [reference.md](reference.md)「参数注册表」 |
| C-34 | `OPS-4` | 回退演练:回填了结后切回,旧系统不重处理已产生业务效果的消息;在途窗口处置见 `Q21` |
| CLM-11(单实例防线) | `OPS-1` | 配置错误启动失败测试可验收;「双实例同时启动只允许一个处理」未闭环——系统无运行时互斥,达成方式待 `Q29` |
| PRE-9(测试隔离) | `OPS-3` | 测试环境配置核对:独立的数据库、Redis 与 Kafka 主题,不连接生产信箱 |