diff --git a/docs/requirements.md b/docs/requirements.md index 0ea6904..c90c8ab 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -1,303 +1,202 @@ # 需求与验收目标 -本文件定义阶段 A 的范围、非目标与验收口径:**需求定义要交付什么,验收标准定义怎样证明完成**。以下事实以本文件为唯一出处: +本文件定义交付范围、非目标与验收口径:**需求定义要交付什么,验收标准定义怎样证明完成**。以下事实以本文件为唯一出处: -- `US-01`~`US-15`(三级标题定义)、`OPS-1`~`OPS-4`(注册表定义); -- 需求覆盖与依赖关系。 +- `US-01`~`US-14`(三级标题定义)、`OPS-1`~`OPS-4`(注册表定义)。 代码入口与参数取值不在本文件:前者见 [reference.md](reference.md)「模块与代码入口」,后者见其参数表。前提、不变量、契约与偏差见 [specification.md](specification.md);机制、航班域与静态参考数据见 [implementation.md](implementation.md)。工程纪律(工具链、测试设施、提交规范)以根 `AGENTS.md` 为唯一出处。 ## 1. 范围与非目标 -**阶段 A 闭合**:`US-01`~`US-14`、`OPS-1`~`OPS-4`。 +**系统定位**:OMMS H5 查询系统的消息网关。收取 CIIMS adapter 信箱中 AODB 下发的 XML 报文:航班动态写入数据库并同步写 Redis,运营航班的动态消息经 Kafka 发给运营航班显示界面实现同步;静态参考数据写入数据库,供 admin-api 只读。出站仅向 AODB 发参考数据类请求(经 `COUTMSGS`,消费方为 CIIMS adapter)。 -**本版本主要新增能力**:从入站 SIS 消息解析、校验并发布静态参考数据(`US-13`),供 admin-api 从处理后的业务数据库读取(`US-14`)。 +**交付范围**:`US-01`~`US-14`、`OPS-1`~`OPS-4`。 + +**本版本主要新增能力**:静态参考数据同步(`US-13`)。 **非目标**: -- 航班当前态只存自有 PG;不引入 Redis、阶段 A 的 ES 投影、新业务库、并行主泵或分布式锁。 -- 共享 MySQL 只做契约内读写与回填;不建表、不增列、不迁移、不写共享历史表(`C-14`)。 -- 生产保持单活动实例;不承诺端到端恰好一次、跨 `FLID` 顺序或未经验证的 Oracle 11g 支持。 -- `US-15` 未启用前遵守 `D1`:历史写入未确认成功时航班清场删除 0 条。 -- 不生成上游业务报文,不替代 CIIMS/AODB,不提供 AODB 主数据编辑能力。 -- 本网关不调用 admin-api,也不从 admin-api 拉取、补全或合并任何数据;admin-api 只从本网关处理后的 PostgreSQL(或通过适配验证的 Oracle)读取。 +- 航班当前态权威只在自有 PG;Redis 仅作查询投影,不作权威或处理状态。不引入并行主泵或分布式锁。 +- 共享 MySQL 只做读写消息和写回处理标记,不改表结构、不建表、不清数据。 +- 本消息网关只有一个实例,暂不考虑多实例运行方案。 +- 对外投递只承诺至少一次;同一航班(`FLID`)内保序,不同航班之间不承诺顺序。 +- 测试环境用 PostgreSQL;生产环境尚未决定用 PostgreSQL 还是 Oracle 11g,Oracle 适配验证通过前不构成支持承诺。 +- 已结束的航班写入 Elasticsearch 历史库后从实时数据删除。 +- 不生成航班/业务数据类报文,不替代 CIIMS/AODB,不提供 AODB 主数据编辑能力。 +- 不调用 admin-api,不从 admin-api 拉取、补全或合并任何数据。 -## 2. 阶段 A 用户故事 +## 2. 用户故事 ### US-01 可靠采集共享信箱 -**目标**:上游继续向 `CMINMSGS` 落信,本系统持续、可恢复地采集,不要求上游改投递方式。 +**目标**:本系统持续、可恢复地从共享 MySQL 信箱读取上游写入的消息,不丢、不漏。 **验收标准** -1. 按配置周期、ID 升序、有限批次采集信箱行;扫描谓词以 [implementation.md](implementation.md)「收报与水位」为准(按 ID 区间,不以处理标记为谓词)。接收层只入队,不解析业务、不回填已处理标记。 -2. 按信箱 ID 幂等建立 PG `PENDING`;重复扫描、并发兼容入队和进程重启都不能重置已有终态。 -3. 快路径用持久水位,本批 PG 入队全部确认后才推进水位。 -4. PG 不可用或批次中途失败时不改信箱标记;恢复后补建遗漏,记录失败次数与扫描进度。 -5. 较小 ID 迟提交、ID 有空洞、兼容入口先入队较大 ID 时,必须遵守经 `Q2` 确认的发现与顺序协议;不能用「最终会重扫」冒充严格 FIFO。 +1. 按配置周期查信箱中「处理时间为空」的消息,每次一批有上限;已处理的消息不再重复采集。 +2. 同一条消息只会被登记和处理一次:扫描重来、重启恢复都不会造成重复处理。 +3. 消息按到达顺序处理(信箱编号即到达顺序)。 +4. 本系统故障期间信箱消息不受影响;恢复后从「处理时间为空」的消息继续,不丢、不漏。 -**前置**:共享库读契约;`Q2` 决定严格顺序的端到端验收;水位与扫描谓词口径以 [implementation.md](implementation.md)「收报与水位」为准。 +### US-02 兼容 HTTP 注入报文 -### US-02 兼容 HTTP 注入报文(KEEP) - -**目标**:联调工具通过 `POST /cminmsgs/send` 提交 XML,得到真实的信箱接收结果。 +**目标**:提供 HTTP 接口 `POST /cminmsgs/send`,联调工具可把 XML 报文直接写进信箱,效果与上游投递一致。 **验收标准** -1. 支持 `text/xml`、`application/xml`、`text/plain`,默认 UTF-8;空报文、超过请求体上限(见 `C-28`)的请求和畸形 XML 返回规范错误,不落信。XML 校验禁用 DTD、外部实体与外部资源访问。 -2. 信箱确认落信后返回 ID;PG 入队失败不把已落信伪装成未接收,由 `US-01` 补建。信箱写入未确认时不返回成功。 -3. 目标为兼容 `ResponseDto`;固定成功/失败样例、HTTP 状态码、响应媒体类型和错误码表后加入契约测试,见 `Q3`。成功只承诺信箱落信,不承诺业务处理或下游完成。 -4. 生产保持内网信任边界,由网关限制来源并审计;外露或跨网络必须先落实认证,不能把免密入口直接暴露。 +1. 报文为 XML,支持 `text/xml`、`application/xml`、`text/plain`,默认 UTF-8。 +2. 空报文、超大小上限、格式错误的 XML:返回错误,不写入信箱;解析禁用外部实体与外部资源访问。 +3. 写入成功返回信箱编号;写入失败返回失败,不返回编号。 +4. 成功只表示报文已进信箱,不代表已处理或下游已收到。 +5. 仅限内网使用,由网络层限制来源。 -**目标响应体示例**(数字和错误码仅作示例,错误码表见 `Q3`): +### US-03 按顺序、不重复地处理消息 -```json -{"is_success": true, "body": 12345} -{"is_success": false, "err_code": "", "err_msg": ""} -``` - -**前置**:`US-01` 补建能力;`Q3`。HTTP 基础格式校验不替代 `US-03` 的业务解码。 - -### US-03 严格按序、幂等地执行管道 - -**目标**:报文失败和重试不造成航班状态倒序,也不重复产生副作用。 - -**实施拆分**:调度与时钟 → 安全解码及路由 → 身份绑定 → 状态应用与 PG 提交。先用假处理器验证管道,不等 `US-05` 全部实现。 +**目标**:消息按到达顺序逐条处理;同一条消息不会产生两次效果。 **验收标准** -1. 只取最小未完成 ID,`PENDING / FAILED` 均占队头;退避未到期不得越过。维护作业由独立线程执行,不参与消息 FIFO;作业必须有界,且不得因争用资源使已到期消息无限饥饿。 -2. 安全解码 XML,至少覆盖 META、SCHD、FLOP、参考应答与忽略类路由;合法但能力未支持是 `UNSUPPORTED`,不能一律归为非法报文。保留原文以支持诊断和回放。 -3. 解码后首次绑定 `SNDR|TYPE|STYP|SEQN`;冲突转 `SKIPPED` 并记录原 ID;自身重试保留绑定。生产按 `PARAM:msgx.identity.include-day-boundary` 配置(当前口径不含日期边界);更改算法须先确认 `Q11`。 -4. `MALFORMED` 直接 `DEAD`;`CODEC_ERROR / UNSUPPORTED / INFRA` 按次数和退避处理,耗尽转 `DEAD(EXHAUSTED)`。不能无限重试未实现类型,也不能立即当非法报文丢弃。 -5. 终态判据只有尝试上限(`PARAM:msgx.pipeline.max-attempts`),**没有按时间的毒丸**;调度判断注入 `Clock`。人工重放的可重放范围以 `Q6` 决定的 `R_keep` 下界为准。 -6. 主泵在同一 PG 事务提交航班主表/明细、事件与处理结果;终态回填意图通过 `US-09` 同事务保存。任一步失败整体回滚;提交后只重试外部回填,不重复生成业务事件。 -7. 决策、事务与落库的职责边界以 [implementation.md](implementation.md)「消息、身份与决策」与 `INV-17` 为准;本条验收面是:失败只在持有消息上下文的边界落账,中断向上传递,不作为普通失败吞掉。 -8. 权威存储不可用或未完成恢复时停止业务处理;不能把「整个状态丢失」误判为「单航班不存在」而批量成功结束增量报文。 +1. 一次只处理一条消息,取编号最小的未完成消息;处理中的消息不让后面的越过。 +2. 报文不合法:进死信。报文合法但本系统不支持该类型:跳过留档,按已处理写回标记。原始报文始终保留。 +3. 处理或提交失败:事务回滚,消息保持未完成,下一轮自动重新处理。 +4. 处理只动本系统数据库;发 Kafka、回填信箱在处理完成之后单独做。 +5. 错误必须记录到对应消息的处理记录上,不能被外层吞掉。 -**前置**:`US-01`;`Q1` 已定单库方向,`Q6` 决定 `R_keep` 下界(重放窗口)。数据库迁移只落自有库。 +### US-04 处理计划外航班(ADFT) -### US-04 明确忽略非业务报文(KEEP) - -**目标**:无需处理的报文有可追踪的终结结果,不制造无效重试与死信。 +**目标**:AODB 计划外新增的航班(临时加班、ATC 指定)建立到本系统。 **验收标准** -1. 解码 META 后、处理器分派前,大小写不敏感匹配 `TYPE-STYP` 或 `TYPE-*`;基线为 `LDM-* / EROR-*`,不混用 `ERROR`。`REGN` 与 `RSTA` 属 `US-13` 的参考数据入口,不得按忽略规则截断。转 `SKIPPED` 前必须已完成身份绑定(`US-03`、`INV-9`),忽略报文照常绑定身份。 -2. 命中后转 `SKIPPED`,记录 `ignored:` 和计数;不更新航班、不创建业务通知。 -3. 通过 `US-09` 保存回填意图;命中、未命中、大小写和重扫均有测试。合法忽略报文不应因 `MsgKind` 尚不能表达它而先解码失败。 +1. 航班不存在:创建,字段按报文内容落库;带了计划时间则算出运营日,没带则留空等日计划收录。 +2. 航班已存在:按报文更新携带的字段,未携带的不清空。 +3. 航班处于已删除状态时收到 ADFT:按报文内容恢复航班。 -**前置**:`US-03` 解码/终态接口、`US-09`。 +### US-05 应用运营航班动态(FLOP) -### US-05 应用 ADFT 与 FLOP(KEEP + FIX) - -**目标**:增量报文正确更新航班及主/共享关系,并生成符合现役语义的通知。 +**目标**:运营航班的动态消息(时间、资源、状态变化)如实落到航班数据上,并发 Kafka 消息通知网页客户端。 **验收标准** -1. 动态子类型以 SIS `SIS:3.19`~`SIS:3.43` 的 25 类为权威;逐类字段、空标签、方向与处理例外见 [implementation.md](implementation.md)「动态运行事件」。SIS 未定义但 legacy 处理的类型只作待对拍候选,按 `Q8` 定案;RESP/DNLD 走 `US-06`。 -2. 每个启用子类型必须有「输入与前态 → 目标状态 → 终态与事件」golden,并覆盖字段缺失、显式清空、重复报文和不存在/已删除航班。未知子类型必须按 `UNSUPPORTED` 失败,不能进入通用合并。 -3. 对按 KEEP 规则需忽略的不存在航班,以 `SUCCEEDED` 无副作用结束,并由 `US-09` 回填;ADFT 建航班等行为按各类型矩阵执行。航班当前态以自有 PG 为唯一权威,重启即恢复,不存在 Redis 全损后白名单无法找回的损坏路径。 -4. 共享航班更新与删除级联语义以 [implementation.md](implementation.md)「删除与重建」为规范(共享航班通知、主航班 `MAFL` 更新、级联删除、原子变更;不出现主已删、子残留);本条目验收实现不偏离该规范,目标不存在时幂等成功。 -5. ADFT/FDEL 的值相等比较与半状态禁止规则见 [implementation.md](implementation.md)「删除与重建」。 -6. PSDT 只更新消息携带的机位分配;登机桥编码只按 SIS 消息中的 `ABTM.ABDG` 处理,不从 admin-api 查询或派生。 -7. 方向、截断与未映射字段必须符合「动态运行事件」;当前实现偏差由 `G-FLOP-DIRECTION`、`G-FLOP-UNMAPPED` 与 `G-FLOP-SEMANTICS` 统一登记,不得静默丢弃或误处理。 +1. 动态消息的子类型共 25 类,处理规则以 AODB 与本系统之间的消息接口规范(SIS)为准;规范里没有但现场会发的 7 类(靠桥、延误、计划机位等),按现有处理逻辑延续。 +2. 每个子类型有明确的处理规则:更新哪些字段;报文里字段为空表示清除还是撤销;航班不存在时怎么办。 +3. 柜台、转盘、滑槽、登机门、机位五类资源分配报文,现场 AODB 实际会发,照常接收处理(消息接口规范写的是相反方向,与 AODB 核对确认);航线路线最多保留 4 条;报文里有但本系统不存的字段,记录在案,不悄悄丢掉。 +4. 数据写入 Redis 成功,这条消息才算处理完成;写失败不标记已处理,下轮重新处理。 -**前置**:`US-03`;`Q1`、`Q8`、`Q14`。 +### US-06 删除航班(FDEL) -### US-06 导入 RESP/DNLD 日计划快照 - -**目标**:主动下发和请求应答使用同一套全量计划处理,迟到应答不覆盖新状态。 - -| 报文 | 路由 | 请求状态 | 无匹配时 | -|---|---|---|---| -| `SCHD-DNLD` | ScheduleProcessor | 不更新请求 | 不要求开放请求 | -| `SCHD-RESP` | 匹配守卫后进入 ScheduleProcessor | 成功提交时匹配 RQFD → DONE | SKIPPED、审计,禁止更新快照 | -| `SCHD-ADFT` | `US-05` 增量处理器 | 不更新请求 | 不适用 | +**目标**:按 AODB 指令删除航班;共享航班与主航班联动删除,不允许删了一半。 **验收标准** -1. RESP/DNLD 共用流式解析、整包校验和规范化;校验失败不发布半包,旧快照保持可用。 -2. RESP 仅匹配未过期、已发送的开放 RQFD;`DTTM < SENT_AT`、已过期、已被替代或无匹配时,不写业务状态,记录跳过原因。 -3. 在自有 PG 单事务内,批处理写入已校验的 `FLIGHT_SCHD` 航班状态与资源明细;本次日计划中未出现的航班不因此被删除。 -4. 在同一 PG 事务中提交 `FLIGHT_SCHD` 变更、`MSG_EVENT` 待发通知与 `PROC_STATE(SUCCEEDED)`;匹配 RESP 同事务完成请求并置 `DONE`;提交后信箱回填由扫描承接。 -5. 相同报文重放不二次写入或重复发事件;单事务崩溃整体回滚,重放幂等。 +1. 删除航班:标记已删除、从 Redis 移除、发 Kafka 删除消息通知网页客户端;Redis 移除成功才算处理完成,失败下轮重新处理。 +2. 删除共享航班时联动更新其主航班;删除主航班时级联删除其共享航班。 -**前置**:`US-03`、`US-08` 请求登记/匹配基础;`Q1`、`Q5`、`Q13`。 +### US-07 导入日计划(DNLD / RESP) -### US-07 可靠、有序地投递 Kafka +**目标**:日计划是 AODB 当前时刻的完整航班列表:AODB 主动下发(DNLD)或本系统请求后应答(RESP),收到即整体替换本地数据——请求日计划就是主动与 AODB 全量同步一次。 -**目标**:状态应用完成后投递通知;重试可识别、不乱序、不静默丢失。 - -**验收标准** - -1. `KAFKA:msg` 按目标内 `EVENT_ID` 顺序发送,确认后才标 `SENT`;队头退避时不跳过,发送有超时上限。 -2. `KAFKA:schd` 只通过 `flushSchd` 聚合,聚合周期与批上限见 reference;同一 FLID 取批内最新状态,成功确认覆盖对应原事件,失败保持批次可恢复并退避,耗尽可见为 `DEAD`。 -3. 外部接收成功、本地确认失败或进程重启后允许重发;事件标识跨重发稳定,消费者有去重约定,不宣称端到端恰好一次。 -4. 当前 `KAFKA:msg` 与 `KAFKA:schd` 的分区键均为 `FLID`,schd 逐 `FLID` 发送最新状态,不再是 legacy 的多航班数组。`msg` 是否需按 `SNDR` 分区、发送粒度与去重标识的放置以 `Q4` 定案为准;定案前不宣称单分区之外的顺序保证。 -5. 生产强制 `D3` 的三项生产者约束(取值见 [reference.md](reference.md) 参数表);Broker 支持幂等生产协议并完成实际验证,不允许非幂等降级通过验收。 -6. 普通/聚合发送失败、确认丢失、批次标记中断和目标阻塞均有测试;DEAD 保留记录并告警。 - -**前置**:`US-03` 事件提交;`Q4`、现网 Broker 验证。wire 不兼容的标识字段不能直接加到现役载荷。 - -### US-08 发起并跟踪 15 类 AODB 请求 - -**目标**:区分请求登记、出站落信、等待、完成与超时,不把过期应答应用到新请求。 - -**实施拆分**:请求登记/出站补偿 → 匹配/超时 → 14 类参考应答;RQFD 快照效果由 `US-06` 集成验收。 - -**验收标准** - -1. 覆盖 14 类 RQRD 参考请求和 1 类 RQFD-NONE;逐类名称、编码和映射见 `Q8`。 -2. 先持久化 `PENDING` 与出站意图;COUTMSGS 确认落信后关联其 ID 并标 `SENT`,不宣称对方已发送。落信成功而 PG 未确认时可恢复,不能盲目重发。 -3. 同类开放请求最多一个,新请求使旧请求 `EXPIRED`,并发登记不产生两个开放请求。从确认落信的发送时间起算,超时值按 `Q5`;`PENDING`/`SENT` 均不得成为永不超时的死分支。 -4. 优先按已确认的 SEQN 回显匹配;无回显的降级匹配按 `Q5` 明确风险,只接受已发送开放请求且 `DTTM ≥ SENT_AT`。统一转换为可比较的时间,不能把报文日期数字直接与 epoch 毫秒比较。 -5. 迟到、无匹配或已关闭请求的应答不得更新数据,转 `SKIPPED` 并审计。参考应答成功写入 `REF_MASTER` 后,与请求完成、处理终态和事件在 PG 边界内保持所需原子性。 -6. `POST /schd/sync` 复用请求入口,采用 24 小时制和非空/区间校验;响应明确已登记还是已落信,不承诺计划已更新。 - -**前置**:`US-01`、`US-03`;`Q5`、`Q8`、`Q14`、出站信箱去重契约。请求基础不依赖 `US-06`。 - -### US-09 持久化补偿回填信箱 - -**目标**:本地处理终态最终反映到共享信箱,不因共享库故障回滚已完成业务。 - -**验收标准** - -1. PG 终态与回填意图同事务保存;所有终态路径都经过统一提交边界,不只覆盖成功路径。事务回滚时不得留下可执行回填意图。 -2. 提交后由后台执行回填,主泵不等待共享库;失败按持久记录退避,重启继续执行,不重新执行已完成业务。 -3. SUCCEEDED、规则忽略、身份重复、DEAD 均需回填处理时间;PENDING/FAILED 禁止回填。具体 STATUS 编码按 `Q7` 确认,内部终态不能直接当作外部字段值。 -4. 重复补偿效果幂等,保留稳定的完成时间与审计;重放后的新处理结果不能被旧回填任务覆盖。非法报文缺 META 时也有明确回填方式。 -5. 影子模式禁写,双跑仅一个系统持有标记写权;暴露 PG 终态、回填状态、积压、最老年龄与持续失败告警。 - -**前置**:`US-03` 终态接口;`Q7`、共享库更新权限。覆盖四类终态、事务回滚、重复补偿和重放竞争;生命周期与超期补写以 [implementation.md](implementation.md)「中断恢复」「回填」为准,清除口径以 [specification.md](specification.md)「契约」为准。 - -### US-10 安全重放与故障处置 - -**目标**:运维能定位失败、限定恢复范围,并了解重放对当前航班状态的影响。 - -**验收标准** - -1. 按 ID、错误类、时间查询次数、错误、关联事件与回填状态;重放前预览范围,记录操作者、原因和逐项结果。 -2. 仅 `CODEC_ERROR / UNSUPPORTED / INFRA / EXHAUSTED` 的 FAILED/DEAD 允许申请重放;MALFORMED 与其他不允许项不改状态,返回跳过原因。 -3. 重置 attempts/nextAttemptAt,保留身份、原始入队时间和错误审计;可重放范围受 `Q6` 决定的 `R_keep` 下界(原文保留窗口)约束。重新入队仍按 ID 处理,但不承诺已执行过的后续消息自动撤销。 -4. DEAD 之后可能已有新状态,必须预检版本与覆盖风险;不安全时拒绝直接重放,改用经批准的隔离重建或恢复流程,禁止无保护的全量 `replayAll` 生产入口。 -5. 操作有认证、授权、范围限制与审计;死信、持续补偿失败、队列年龄越界有告警和处理 Runbook。 - -**前置**:`US-03`、`US-09` 的恢复状态;`Q6`、`OPS-1`/`OPS-2` 的安全与可观测基础。 - -### US-11 归档自有库终态记录 - -**目标**:控制自有 PG 在线表规模,不丢未完成工作、不破坏去重与恢复;不是清理共享信箱。 - -**验收标准** - -1. 终态记录在**了结后**经过的时间(`UPDATED_AT`)达到 `PARAM:msgx.proc-state.archive-after` 时列为归档候选;`PENDING`/`FAILED` 禁止归档,回填未了结的终态行不进入候选。 -2. 归档到自有 PG `PROC_STATE_HST`,主表保留 `STATE='ARCHIVED'` 的去重影子行(仅 `IDENTITY_KEY` 与 `MSG_ID`),使归档后同业务身份再次到达仍可去重;`MSG_EVENT` 的历史目标与保留规则由投递清理独立处理,不构成归档判据。 -3. 归档写入与主行置 `ARCHIVED` 在同一自有库事务内完成,按候选时的状态条件复查,影响 0 行即整体回滚;重复执行幂等,失败保留源记录并报告计数。 -4. 本系统不写共享 MySQL `CMINMSGS_HST`、不清理外部信箱;由库方按 `Q9` 执行的清除与历史归档见 [specification.md](specification.md)「契约」。原文可用性与重放保留期由 `Q6`/`Q7` 关联确认。 - -**前置**:`US-03`、`US-09`;`US-07` 提供事件终态规则,`US-10` 提供恢复保留要求。不依赖 `US-15`。自有记录归档见 [implementation.md](implementation.md)「生命周期与清除」。 - -### US-12 查询实时航班(KEEP) - -**目标**:调用方读取与当前权威状态一致的实时航班视图。 - -**验收标准** - -1. 保留 `GET /all/flights`,直接从自有 PostgreSQL `FLIGHT_SCHD` 查询,排除共享航班(`MAID != NULL`,定义见 [implementation.md](implementation.md)「字段与集合」);不改写业务状态。 -2. 固定响应样例、空结果、排序、大小限制及一致性时点。现役未分页时不能无声改为只返回第一页;分页或响应结构变更按 `Q3` 决定。 -3. 依赖异常不能伪装为空数组成功;影子只读影子状态,入口有约定的访问控制、限流与审计。 - -**前置**:`Q1`、`Q3`;所查询的 `US-05`/`US-06` 状态发布能力。 - -### US-13 从 SIS 消息刷新静态参考数据 - -**目标**:消费 AODB 经共享信箱投递的 SIS 消息,形成业务可用的本地静态参考数据;刷新失败仍保留上次可用版本。 - -**验收标准** - -1. 通过 `CMINMSGS` 消费 SIS `SIS:3.1`~`SIS:3.14` 的 13 类参考数据与资源状态消息;类别、`RTYPE`/`RKEY` 与结构见 [implementation.md](implementation.md)「静态参考数据」。这是独立于 `US-08` 请求入口的消息处理能力,不另建「参考专用第二 PG」。 -2. 静态参考数据只能来自上述 SIS 消息,禁止从 admin-api 拉取、补全或合并;admin-api 仅作为处理结果的下游读取方。 -3. 按 `(RTYPE,RKEY)` 幂等写 `REF_MASTER`,记录消息来源、刷新时间和批次;单类完整校验后发布,失败不暴露半批。 -4. 一类失败不破坏其他类或该类旧版本;`DNLD`/`RESP` 的全量替换与 `ADD`/`UPD`/`DEL` 的增量合并严格按消息语义执行。 -5. 影子默认不主动刷新生产数据;需要参考样本时显式导入隔离副本。 -6. `SIS:3.1`~`SIS:3.13` 按 `STYP` 区分全量与增量;`RSTA` 遵守 `SIS:3.14` 的单条 `DNLD` 与多条 `RESP` 语义,不把 `DNLD` 当作全量替换。参考数据的空标签表示「数据不可用」而非删除,不得套用航班动态的空标签合并规则。 - -**前置**:`US-01`、`US-03`、`Q8`。必须复用统一的入站消息管道、身份绑定和处理终态。 - -### US-14 向 admin-api 提供数据库读取结果 - -**目标**:admin-api 从本网关处理后的业务数据库读取航班状态与静态参考数据,网关与 admin-api 之间不存在反向调用。 - -**验收标准** - -1. 数据流固定为「SIS 消息 → 本网关处理 → PostgreSQL / 经验证的 Oracle → admin-api 只读」;禁止实现 admin-api → 本网关的 HTTP、数据库或缓存取数路径。 -2. admin-api 只能读取已原子提交的航班状态与静态参考数据,不得看到参考数据半批,也不得成为网关处理成功的前置条件。 -3. 对 admin-api 的物理表、视图和查询契约按 `Q8` 定案;不得据本需求改动共享 MySQL schema。 - -**前置**:`US-13`、`Q1`、`Q8`。 - -### US-15 历史航班清场(DEFERRED,阶段 B) - -历史存储确认成功后,才允许删除对应实时航班;逐条隔离坏数据,不能删除写历史失败的集合。判史规则与保留期、业务时区、历史写入与删除事件之间的恢复协议需在启用前完成 golden 对拍。 - -阶段 A 不依赖 ES,不启用 `PROJECTION_REBUILD`。历史清理作业在历史存储未接通(`PARAM:msgx.history.history-store-enabled` 关闭)时删除 0 条;红线见 [implementation.md](implementation.md)「生命周期」。 - -## 3. 运行与切流验收 - -| 编号 | 必须交付的能力 | 验证证据 | -|---|---|---| -| OPS-1 单写者与启动安全 | 生产缺真实适配器、误用 stub、未启用必需管道时拒启;第二活动写者不能启动,失去写权后不得继续写;中断与停机能正确退出。 | 配置拒启、双实例/失去写权及停机测试。单靠副本数配置不算运行期保护。 | -| OPS-2 可观测与安全 | 真实依赖健康、队列/队头年龄、投递/回填滞后、积压与最老未处理信龄、DEAD 和一致性异常有指标、告警与处理入口;敏感管理操作有访问控制,日志不泄漏口令或完整敏感报文。 | 故障注入触发真实告警,消息到事件可关联;日志出口断开不阻塞业务。 | -| OPS-3 影子隔离 | 自有数据库/schema、topic、服务注册身份隔离;输入只读水位或回放,禁生产回填、真实出站和误注册。 | 配置与集成测试证明生产信箱、状态、topic 未被影子修改。 | -| OPS-4 切流与恢复 | 对拍不少于 7 天,未解释业务字段差异为 0,DLQ 积压为 0,`MSG_EVENT` 最老滞留 < 5 秒;切流后 48 小时观察,24 小时内具备经演练的回滚能力。 | 明确负载与统计口径的对拍报告;Runbook 含停写、排空/水位、状态恢复、写权交接和失败回退,不能只回滚程序版本。 | - -上述阈值沿用既有需求基线,需在真实环境提供证据。自有库备份、报文保留和完整状态重建需要恢复演练;本地事务不能承诺任意数据库灾难下 RPO=0,也不承诺未经演练的「一键无损回滚」。 - -## 4. 需求覆盖与依赖 - -### 4.1 覆盖矩阵 - -| 需求 | 必须闭合的能力 | 约束 / 偏差锚点 | -|---|---|---| -| `US-01` | 按 ID 有限采集、持久水位、幂等入队、空洞与中断恢复 | `INV-2`~`INV-5`、`Q2` | -| `US-02` | 安全兼容注入,落信确认与业务完成分离 | `C-28`、`Q3`、`G-COMPAT-HTTP` | -| `US-03` | 严格 FIFO、安全解码、身份去重、事务提交与持久重试 | `INV-3`、`INV-6`~`INV-10`、`INV-17`、`Q6`、`Q11`、`Q15` | -| `US-04` | 忽略报文在身份绑定后无业务副作用终结并回填 | `INV-8`、`INV-9` | -| `US-05` | ADFT、FDEL、SIS 25 类 FLOP、完整航班态及主/共享关系 | `INV-11`~`INV-22`、`Q8`、`Q13`、`Q14`、`Q16`、`G-FLOP-IDEMPOTENT`、`G-FLOP-DIRECTION`、`G-FLOP-UNMAPPED`、`G-FLOP-SEMANTICS`、`G-MAFL`、`G-SRVT-VIPF` | -| `US-06` | DNLD/RESP 整包快照、请求守卫、迟到应答隔离 | `INV-12`、`INV-15`、`INV-19`、`Q5`、`Q13`、`G-RESP-GUARD` | -| `US-07` | Kafka 至少一次投递、同 `FLID` 保序、schd 聚合、失败与清理 | `D3`、`INV-10`、`C-29`、`Q4` | -| `US-08` | 14 类 RQRD、1 类 RQFD、出站落信、开放请求唯一、匹配与超时 | `C-23`、`C-24`、`Q3`~`Q5`、`Q8`、`Q10`、`Q14`、`G-REQ-TRACK`、`G-REQ-OPEN-UNIQUE`、`G-REQ-TRACK-RETENTION` | -| `US-09` | 终态回填意图、后台补偿、四结果、放弃与人工恢复 | `INV-7`、`INV-8`、`C-5`~`C-8`、`Q7`、`Q9`;`C-6` 不成立时闭合 `G-REPLAY-CHANNEL` | -| `US-10` | 可查询、可预览、白名单重放、风险预检、授权与审计 | `CLM-3`、`Q6` | -| `US-11` | 已了结终态归档、去重影子、竞态复查及独立保留期 | `D4`、`C-14`、`C-16`、`G-PROC-HST`、`G-HST-RETENTION` | -| `US-12` | 从 PG 权威态查询实时主航班,固定契约且依赖失败不伪装为空 | `INV-11`、`Q3` | -| `US-13` | SIS 消息中的 13 类参考数据与资源状态:完整校验、原子发布、失败保旧 | `Q8`、`G-REF-DATA` | -| `US-14` | admin-api 从本网关处理后的 PG / 经验证 Oracle 只读消费,不形成反向依赖 | `Q1`、`Q8`、`G-REF-DATA` | -| `US-15` | 阶段 B 历史归档成功后清场及删除事件恢复 | `D1`、`INV-18`、`Q9`、`G-FLIGHT-HIST-RETENTION` | -| `OPS-1` | 真实适配器、配置与单写者拒启,失权停写,安全停机 | `D2`、`PRE-5` | -| `OPS-2` | 真实健康、积压/失败指标、告警、受控处置与敏感信息保护 | reference.md | -| `OPS-3` | 影子数据库、topic、服务身份隔离并禁生产写 | `PRE-1` | -| `OPS-4` | 对拍、切流观察、恢复演练及完整回退规程 | `C-1`~`C-29` | - -### 4.2 契约依赖索引 - -`Q` 的定义与完整表述只在本文件之外一处:[specification.md](specification.md)「待确认事项台账」。此处只列与验收直接相关的依赖: - -- `US-01` / `US-09` 的验收依赖 `Q2`(发现完整性)与 `C-8`(清除前提); -- `US-06` / `US-13` 依赖 `Q8`(逐类清单)与 `Q13`(字段缺失语义);`US-14` 依赖 `Q1` 与 `Q8`(下游数据库读取契约); -- `US-08` 依赖 `Q3`(HTTP 契约)、`Q4`(Kafka wire)、`Q5`(请求匹配)、`Q10`(出站契约); -- `US-10` 依赖重放白名单与 `CLM-3`(重放安全); -- `US-15` 依赖 `Q9`(清除授权与 DDL)。 - -业务日期/日计划采用 `Asia/Shanghai`;持久化与比较使用明确的时间类型和转换规则,不靠服务器默认时区,也不直接比较不同单位的数字。 - -## 5. HTTP 工具边界 - -| 端点 | 范围 | +| 报文 | 说明 | |---|---| -| `POST /cminmsgs/send` | `US-02`,保留接收兼容性。 | -| `POST /schd/sync` | `US-08`,保留并修正参数校验;不等同于同步完成快照。 | -| `GET /all/flights` | `US-12`,保留查询语义。 | -| `POST /kafka/topics/{name}/msgs` | 不进生产;开发工具若保留,另行限制 topic allowlist。 | -| `GET /flights/migrate` | 不做,属于 legacy 一次性迁移工具。 | +| `SCHD-DNLD` | AODB 主动下发,直接处理。 | +| `SCHD-RESP` | 本系统请求后的应答,只在请求未过期时生效;迟到的应答不更新数据。 | + +**验收标准** + +1. 报文整体校验(声明的航班数、航班标识等)通过才处理;校验失败整包拒绝,本地数据不变。 +2. 报文里的航班逐条写入或更新;快照里没有的航班删除,并发删除消息。 +3. 以 AODB 下发的数据为准:日计划里某航班没携带的字段,视为 AODB 已删除该值,本地同步清掉。 +4. 航班量大,分批写入数据库,每批一个事务;处理失败不标记已处理,下轮整包重新处理。 +5. 按快照结果刷新 Redis:报文里的航班写入,缺席的航班移除。 + +### US-08 通知网页客户端(Kafka) + +**目标**:航班数据变化后发 Kafka 消息,网页客户端据此刷新显示。 + +**验收标准** + +1. 两个 Kafka 主题:`msg` 发单条航班变更,`schd` 定时批量发最新状态。 +2. 发送失败自动重试;同一航班的变更按顺序发送。 +3. 发送一直失败的记录保留并可查,有告警。 + +### US-09 向 AODB 请求数据 + +**目标**:本系统可以主动向 AODB 要数据:14 类参考数据 + 1 类日计划(请求类型以消息接口规范定义为准)。 + +**验收标准** + +1. 同一类请求同时只有一个在等待;发新请求时旧请求作废。请求超过时限未等到应答,标记超时。 +2. 应答到达时按报文类型对应到等待中的请求;AODB 发错或迟到的应答不更新数据,记录后跳过。 +3. 收到 EROR(AODB 错误回报):定位到本系统发出的请求,标记失败并告警。 + +### US-10 回写信箱处理标记 + +**目标**:处理完消息,把信箱里对应消息标记上处理时间,保证信箱行最终全部有标记。 + +**验收标准** + +1. 处理完成时在本地记录「待标记」,后台任务把它写到 MySQL 信箱。 +2. 写失败自动重试,重启后继续;一直写不上的记录在案并告警。 + +### US-11 处理记录清理 + +**目标**:处理记录只用于追踪消息处理情况和排查问题,没有长期保留价值;定期删掉老记录,防止表无限增长。 + +**验收标准** + +1. 处理完、标记也写回信箱的记录,超过保留期后删除;没处理完的不删。 +2. 保留期可配置。 + +### US-12 查询全部航班 + +**目标**:提供查询接口 `GET /all/flights`,返回当前全部动态航班(不含共享航班)。 + +**验收标准** + +1. 从 Redis 读取,与网页客户端查询同源。 +2. Redis 异常时报错,不返回空列表假装正常。 + +### US-13 同步静态参考数据 + +**目标**:接收 AODB 通过信箱下发的机场基础数据(国家、机场、航空公司、机型、登机口、机位等 13 类)和资源状态,保存到数据库,供查询系统使用。 + +**验收标准** + +1. 数据按类别和编号保存,新消息覆盖旧记录。 +2. 一类数据校验不通过就不更新这一类,其他类照常;已有数据不动。 +3. 全量消息整体替换,增删改消息逐条处理。 +4. 消息里字段为空表示「当前没有值」,不是删除。 +5. 参考数据保存在独立的数据表中,查询系统(admin-api)直接读取。 + +### US-14 航班历史与清理 + +**目标**:已结束运营的航班转入历史存储供历史查询使用,并从实时数据中删除,保持实时数据精简。 + +**验收标准** + +1. 每天凌晨定时执行(每日 3:30):读取全部实时航班,已结束的航班写入 Elasticsearch 历史库。 +2. 满足任一条件即视为已结束: + - 计划时间距当前超过 3 天; + - 已取消超过 1 小时; + - 备降:应降本场、实际降其他机场,且计划时间距当前超过阈值; + - 离港航班:计划时间早于当日、有实际起飞时间、且实际起飞不晚于当前; + - 到港航班:计划时间早于当日、有实际到达时间、且实际到达距当前超过 1 小时。 +3. 只有历史写入成功的航班才从实时数据删除;写入失败下次重来,已写入的不重复写入。 +4. 单个航班写入失败不影响其他航班;正在被消息处理的航班跳过,下轮再处理。 + +## 3. 运行验收 + +| 编号 | 要求 | 验证方式 | +|---|---|---| +| OPS-1 单实例运行 | 系统配置不完整时拒绝启动;同一时刻只允许一个实例处理消息。 | 配置错误启动失败测试;双实例同时启动测试。 | +| OPS-2 可观测 | 消息积压、处理失败、发送失败、标记写回失败都有监控指标和告警。 | 故障注入触发告警;检查监控面板。 | +| OPS-3 测试隔离 | 测试环境的实例使用独立的数据库、Redis、Kafka 主题,不连接生产信箱。 | 配置检查。 | +| OPS-4 切换与回退 | 停旧系统、启新系统完成切换;出问题回退时停新、启旧,未处理的消息由旧系统继续,数据不丢。 | 切换与回退演练记录。 | + +## 4. HTTP 接口清单 + +| 接口 | 用途 | +|---|---| +| `POST /cminmsgs/send` | 联调工具写入报文(US-02)。 | +| `POST /schd/sync` | 发起日计划请求(US-09)。 | +| `GET /all/flights` | 查询全部动态航班(US-12)。 |