From 6fa4da60f10e37b856cfdcf2dd81ee14cf59551c Mon Sep 17 00:00:00 2001 From: windyboy Date: Wed, 16 Sep 2026 14:43:38 +0800 Subject: [PATCH] =?UTF-8?q?docs(acm2-75):=20=E6=94=B6=E6=95=9B=202.1-2.4?= =?UTF-8?q?=20=E7=BA=A6=E5=AE=9A=E6=9D=A1=E7=9B=AE=E5=B9=B6=E9=87=8D?= =?UTF-8?q?=E6=8E=92=E7=BC=96=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 已作废条款节 - 更新全文交叉引用 --- docs/specification.md | 132 +++++++++++++++--------------------------- 1 file changed, 47 insertions(+), 85 deletions(-) diff --git a/docs/specification.md b/docs/specification.md index 6198545..f93778f 100644 --- a/docs/specification.md +++ b/docs/specification.md @@ -1,8 +1,8 @@ -# 规范:术语、约定、前提、不变量、声明边界与验证映射 +# 规范:术语、约定、前提、不变量与能力边界 -本文整理 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),对外承诺以本文件为准。 +本文整理 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)。 +`C-x`、`PRE-x`、`INV-x`、`CLM-x`、`Qn`、`G-NAME` 只在本文件定义,编号规则见 [README.md](README.md)。 约定条目的标记: @@ -18,9 +18,9 @@ | 术语 | 含义 | |---|---| | 上游 | 产生报文的 AODB,报文经 CIIMS adapter 写入信箱。 | -| 信箱 | 共享 MySQL 的 `CMINMSGS`(入站)与 `COUTMSGS`(出站),归库方所有;边界见 `C-14`。 | +| 信箱 | 共享 MySQL 的 `CMINMSGS`(入站)与 `COUTMSGS`(出站),归库方所有;边界见 `C-2`。 | | 库方 | 信箱所在的共享 MySQL 管理方,即 CIIMS adapter 方。 | -| 处理标记 | 即信箱行上的处理时间:为空表示未处理,处理完成时写入完成时刻;写规则见 `C-15`。 | +| 处理标记 | 即信箱行上的处理时间:为空表示未处理,处理完成时写入完成时刻。 | | 落信 | 报文写入信箱成为一行;入站由 CIIMS adapter 或兼容入口写入,出站由本系统写入 `COUTMSGS`;入站报文写进信箱后可能尚未登记。 | | 登记 | 本系统在自有 PG 为这条报文建立处理记录,排队等待处理。 | | 处理完成 | 这条消息的结果已经确定——业务改动生效,或明确跳过、进入死信;之后才回填信箱标记、发 Kafka。 | @@ -38,62 +38,29 @@ ### 2.1 共享信箱(库方) -- **C-3** 信箱编号不复位、不复用、不回退,含表轮换、备份恢复与自增归零。不丢消息依赖这条(`PRE-2`、`PRE-3`)。`(待确认 Q2)` -- **C-4** 报文行不可变:同一业务身份(`SNDR`、`TYPE`、`STYP`、`SEQN`)的重发是同一内容。`(待确认 Q15)` -- **C-5** 处理标记即处理时间列:不在该列引入状态码等其它语义,死信、跳过与回填失败的原因记在自有 PG;写规则见 `C-15`。 - 待确认:处理时间列的列名、类型与可空性(`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),该消息占住处理顺序。 - 信箱行在登记前整行消失的,扫描谓词对其不可见,本系统无法发现;防线只剩 `C-7` 的保留期下界由库方遵守(`Q9`)。`(本系统单方承诺)` - 待确认:原文不可得消息的处置口径(`Q22`)。 -- **C-14** 本系统不建表、不改表结构、不迁移 schema、不清数据,也不写共享历史表。 -- **C-15** 处理标记只在空值上写入处理完成时刻,写完不回撤、不覆盖已有值。`(本系统单方承诺)` -- **C-16** 回填失败时在自有 PG 保留记录并告警;该记录在对应信箱行清除前保持可查。`(本系统单方承诺)` -- **C-30** 本系统读取入站信箱 `CMINMSGS` 不加锁、不阻塞写入方,读取谓词、顺序与批量以 `INV-2b` 为准;除回填处理标记(`C-15`)与兼容入口落信(`C-28`)外不写 `CMINMSGS`。`COUTMSGS` 的写入见 `C-24`。 -- **C-34** 切换与回退以信箱处理标记交接(`OPS-4`、`PRE-1`):切回前,每条终态行都必须已打上处理标记。放弃自动重试的行没有标记,本系统写不出任何能阻止旧系统消费它的状态:须先人工恢复重试至打标,或与库方另行定处置(`Q9`),否则切回后这些行会被旧系统再处理。已登记、未到处理完成的消息同样没有交接状态。 - 待确认:在途消息的回退处置(`Q21`)。 +- **C-1** 本系统清理已处理的信箱行:回填完成且超过保留期后才删,处理未完成或回填未完成的行不删。 +- **C-2** 共享 MySQL 不做 Schema 变更,本系统只读写 `CMINMSGS` 与 `COUTMSGS` 两张表。 ### 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 发错、迟到(含过期的 `SCHD-RESP`,`US-07`)的应答一律不更新数据,记录后跳过(`US-09` AC2)。 - 待确认:用哪些字段对应、超时如何判定(`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`(共享航班先删、主航班后删,顺序错乱时 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 的核对确认(`US-05` AC3 实施前提)。 +- **C-3** 业务身份由 `SNDR`、`TYPE`、`STYP`、`SEQN` 四字段组合;`SEQN` 自增,极少重置(消息服务器重启),重置后不会与旧消息冲突。 +- **C-4** 出站请求写入 `COUTMSGS`;交付承诺止于落信。 +- **C-5** 航班删除为标记删除,主航班与共享航班各自独立标记。 +- **C-6** 日计划快照里没有携带的字段视为 AODB 已删除该值,本地同步清除(`US-07` AC3)。 ### 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`)。 +- **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-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]** +- **C-9** 航班变更发到 Kafka 主题 `msg`(单条)和 `schd`(批量)。同一条可能发多次。 +- **C-10** 静态参考数据写入本系统数据库,供 admin-api 只读;本系统不调用 admin-api。 +- **C-11** 航班投影写入 Redis,供 `GET /all/flights` 与网页客户端查询。 + 待确认:key 与 value 结构(`Q20`)。 ## 3. 前提 @@ -108,7 +75,6 @@ | PRE-5 | 单活动实例运行,信箱读取不加锁 | 并行读会让「已处理」判定互相踩踏 | 部署约束 | | PRE-6 | 信箱与自有 PG 之间没有跨库事务 | 回填与清除都不能声称原子 | 架构事实 | | PRE-7 | 报文不可变:同一业务身份的重发是同一内容 | 上游改发正文会被判为重复并静默跳过 | 待确认 `Q15` | -| PRE-8 | `FLID` 在保留期内不复用(见 `C-21`) | 「只进不退」的合并可能压掉新航班事件,旧的删除标记可能删掉在用航班 | 待确认 `Q16` | | PRE-9 | 测试环境与生产隔离:测试实例使用独立的数据库、Redis 与 Kafka 主题,不连接生产信箱 | 测试结论与隔离验收(`OPS-3`)失效 | 部署与配置约束 | ## 4. 不变量 @@ -123,7 +89,7 @@ - **INV-8** 回填只针对已有终态的消息;「还欠一次回填」与终态由同一条语句落库,不存在第二处落账。 - **INV-9** 一信一行、一身份一记录:处理记录按信箱编号唯一,同一业务身份至多绑定一条有效记录。再次发现同一身份的信箱行时不得直接跳过:须与既有记录比对内容,一致才按重复跳过留档(`PRE-7`:重发是同一内容);不一致即 `PRE-7` 失效信号,留档、告警、不产生业务效果,处置待 `Q15` 定案。 - **INV-10** 对外投递至少一次;端到端恰好一次不在交付范围。 -- **INV-16** 回填与 Kafka 投递失败可重试,不回滚已提交的本地业务结果;出站请求写入结果不明时记录告警、不直接重发(`C-24`)。 +- **INV-16** 回填与 Kafka 投递失败可重试,不回滚已提交的本地业务结果;出站请求写入结果不明时记录告警、不直接重发。 - **INV-17b** 航班类消息(增量、删除)的状态变更与待发事件在同一事务提交;处理终态与回填意图在另一事务提交,且晚于 Redis 投影写成功。待发事件在处理完成前不可投递(`US-03` AC4),本句对所有类别生效。日计划的分批与静态参考数据的单事务见架构「主流程」。 - **INV-19** 日计划整包校验失败时整包不落地,既有状态与版本不变(`US-07` AC1)。运营日冲突时的处置未在需求与架构定案(`Q23`)。 - **INV-20b** 处理器幂等(目标不变量,被 `G-FLOP-IDEMPOTENT` 阻断,当前不成立):同一消息在失败重处理与重复发现下都只产生一次业务效果。身份唯一只防「重复记录」,不防「重新执行」;逐类幂等规则补齐并回归前,依赖本条的收敛声明(`CLM-3`)不可作出。 @@ -137,8 +103,8 @@ - **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-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`),闭合前收敛不可声明。 @@ -167,10 +133,10 @@ | 编号 | 承诺 | 依赖 | 现在能否作出 | 限制或原因 | |---|---|---|---|---| | CLM-3 | 失败重处理与重复发现不产生重复业务副作用 | `INV-20b` | 不能 | 逐类幂等规则未补齐(`G-FLOP-IDEMPOTENT`) | -| CLM-4 | 信箱行最终都被写上处理标记 | `INV-7`、`C-15`、`C-16` | 不能 | 一直写不上的行留案并告警(`US-10` AC2) | +| CLM-4 | 信箱行最终都被写上处理标记 | `INV-7` | 不能 | 一直写不上的行留案并告警(`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-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` | @@ -181,20 +147,16 @@ | 编号 | 事项 | 当前假定 | 影响 | |---|---|---|---| -| 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`) | 允许值、保留期取值与时钟基准未定 | +| 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-8`);旧系统按接收超过 1 天归档并删除入站行,是否沿用待确认。见 `C-6`~`C-9` | 清除边界与保留期未定 | -| Q10 | 出站 ACK 与错误列语义、出站行清理与重复落信识别、作废请求的结案与应答处置、写入结果不明时名额的释放 | 交付承诺止于落信(`C-24`) | 出站行清理、去重责任与作废语义未定 | -| Q11 | 上游 `SEQN` 的重置周期与身份是否加日期边界 | 暂不加日期边界 | 身份算法不能定稿 | +| Q9 | 清除方案与保留期 | 本系统自行清理(`C-1`);旧系统按接收超过 1 天归档并删除入站行,是否沿用待确认 | 清除边界与保留期未定 | | 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`) | +| Q24 | `GET /all/flights` 的返回字段与类型、集合外层结构、状态码与错误响应 | 读 Redis 投影、返回当前全部动态航班、不分页(`C-11`);旧系统线索为非共享航班 `SCHD.FLTR` 列表(接口契约「HTTP」) | 查询契约无法定稿 | +| Q25 | `RQRD`/`RQFD` 的子类型清单、发送方取值、时间与序号的构造规则 | 出站只有这两类报文(架构「系统定位与范围」);旧系统线索为 `TYPE=RQFD`、`STYP=NONE`、`SNDR=OSH5`(接口契约「HTTP」) | 出站报文无法编码 | 答复就地更新结论,并按 [README.md](README.md)「维护清单」落到对应条款。 @@ -202,8 +164,9 @@ | 编号 | 事项 | 结论 | |---|---|---| -| Q13 | 日计划未携带字段的删除语义 | 见 `C-26` | -| Q14 | 主/共享删除顺序与 EROR 回报义务 | 见 `C-25` | +| Q11 | 上游 `SEQN` 的重置周期与身份是否加日期边界 | 已定案:`SEQN` 自增,极少重置,重置后不与旧消息冲突,不加日期边界(`C-3`) | +| Q13 | 日计划未携带字段的删除语义 | 见 `C-6` | +| Q14 | 主/共享删除顺序 | 已定案:标记删除,各自独立(`C-5`) | 已闭环 | ### 6.3 本系统与需求方待决 @@ -212,13 +175,13 @@ | 编号 | 事项 | 当前假定 | 影响 | |---|---|---|---| | Q1 | 生产库选型 | 自有 PG 是唯一权威;生产环境用 PostgreSQL 还是 Oracle 11g 不能从三份依据确定,Oracle 适配验证通过前不作支持承诺 | 生产部署验收 | -| Q17 | `POST /schd/sync` 的请求字段与时间格式、成功响应表示已登记还是已落信、状态码与错误响应 | 交付承诺止于落信(`C-24`);旧系统线索为 `{startDate, endDate}` 与 12 小时制时间(接口契约「HTTP」) | 响应契约无法定稿(`C-33`) | +| 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 | 回退时在途消息(已提交业务变更、未到处理完成)的处置 | 回填了结后切换(`C-34`);在途消息无跨系统幂等保障 | 回退演练的验收口径(`OPS-4`) | -| Q22 | 是否在自有 PG 留存入站原文副本,及原文提前清除时已登记消息的处置(含队头是否放行) | 不留存,原文只从信箱读取;提前清除的消息按处理失败保持未完成并告警(`C-12`) | 提前清除的消息不可恢复,处置未定 | +| Q21 | 回退时在途消息(已提交业务变更、未到处理完成)的处置 | 回填了结后切换(`OPS-4`、`PRE-1`);在途消息无跨系统幂等保障 | 回退演练的验收口径(`OPS-4`) | +| Q22 | 是否在自有 PG 留存入站原文副本,及原文提前清除时已登记消息的处置 | 不留存,原文只从信箱读取 | 提前清除的消息不可恢复,处置未定 | | Q23 | 日计划中运营日冲突的处置 | 整包校验失败不落地(`INV-19`);冲突是否属于整包校验未定 | 冲突场景无法验收(`INV-12`) | -| Q26 | `REF_MASTER` 的物理列、唯一键、空值存储与写入后可见时点 | 记录用类别码加识别标签识别(接口契约「静态参考数据类别与编号来源」) | admin-api 读取契约无法定稿(`C-31`) | +| 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` 双实例验收不闭环 | @@ -229,15 +192,14 @@ | 偏差 | 缺什么,会怎样 | 影响 | |---|---|---| -| `G-RESP-GUARD` | `SCHD-RESP` 没有过期判断,晚到的应答也会更新本地数据 | `US-07`;`C-23` | -| `G-REQ-TRACK` | 出站请求没有跟踪:登记、编码、超时与应答匹配都没有实现 | `US-09`;`C-24` | +| `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`;`INV-22` | +| `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` | @@ -250,14 +212,14 @@ | 不变量 | 需求验收 | 要观察的结果 | |---|---|---| | INV-2b | `US-01` AC1/AC2/AC4 | 扫描重来与重启后登记数不变,行不丢 | -| INV-2b、C-28 | `US-02` AC1~AC5 | 兼容入口接受三种媒体类型、默认 UTF-8;空报文、超上限、非法 XML 不落信并返回错误,解析禁用外部实体与外部资源;成功返回编号且只表示落信;内网来源由网络层配置核对;写入的行与上游投递同路径被发现、登记 | +| 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-29 | `US-08` AC1/AC2/AC3 | `msg` 单条变更、`schd` 批量;失败重试后仍能投出且同一 `FLID` 顺序不颠倒(端到端保序待 `Q4`,见 `CLM-7`);一直失败的记录保留可查并告警 | +| 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 | 未携带的字段保持原值 | @@ -268,16 +230,16 @@ | 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-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-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` AC1~AC3 | 请求落信即交付、写入结果不明不重发;在途唯一、超时与 `EROR` 定位告警待 `G-REQ-TRACK`、`G-REQ-OPEN-UNIQUE` 闭合后验证,匹配依据见 `Q5` | +| CLM-8 | `US-09` AC1~AC3 | 出站请求写入 `COUTMSGS` | | CLM-9(不承诺完成时限) | `OPS-2` | 积压、处理失败、投递失败、回填失败各有指标与告警(架构「总体架构」) | | CLM-10(容量假设) | 无对应运行验收 | 上线前用现场量级重估,取值见 [reference.md](reference.md)「参数注册表」 | -| C-34 | `OPS-4` | 回退演练:回填了结后切回,旧系统不重处理已产生业务效果的消息;在途窗口处置见 `Q21` | +| OPS-4 | `OPS-4` | 回退演练:回填了结后切回,旧系统不重处理已产生业务效果的消息;在途窗口处置见 `Q21` | | CLM-11(单实例防线) | `OPS-1` | 配置错误启动失败测试可验收;「双实例同时启动只允许一个处理」未闭环——系统无运行时互斥,达成方式待 `Q29` | | PRE-9(测试隔离) | `OPS-3` | 测试环境配置核对:独立的数据库、Redis 与 Kafka 主题,不连接生产信箱 |