# 接口契约草案 本文记录 msgexchange-v2 与联调工具、运营航班显示界面、CIIMS adapter、admin-api、Elasticsearch 航班历史存储之间需要共同遵守的接口:收报、出站请求与应答、Kafka 通知、Redis 查询投影、共享信箱、参考数据与航班历史。 范围由 [requirements.md](../requirements.md) 与 [architecture.md](../architecture.md) 确定,出处随各条标注;未列出的字段不能作为字段级联调依据。 旧项目用户故事文档([legacy/](../legacy/))只供字段核对,不作为新版契约的依据。 ## HTTP | 接口 | 请求契约 | 成功响应契约 | 失败契约 | 尚需确定 | |---|---|---|---|---| | `POST /cminmsgs/send` | 请求体是 XML 原文;接受 `text/xml`、`application/xml`、`text/plain`,默认 UTF-8;仅限内网,网络层限制来源。 | 报文写入 `CMINMSGS` 后返回信箱编号;写入的报文与上游投递走同一条处理路径、效果一致;该响应只证明已落信,不证明业务处理或下游投递(`US-02`)。 | 空报文、超大小上限、非法 XML 不落信并返回错误;写信失败不返回编号;XML 解析禁用外部实体和外部资源访问。 | 大小上限、请求编码与 `Content-Type` 的精确处理规则、HTTP 状态码、成功/失败响应体字段及样例。 | | `POST /schd/sync` | 触发一次 `RQFD` 日计划请求;请求字段尚未定义,登记与落信规则见「在途与作废」。 | 响应内容尚未定义;无论表示登记还是落信,都不代表 AODB 已收到。 | 错误响应尚未定义。 | 请求字段与时间格式、成功响应表示已登记还是已落信(`Q17`)、状态码、响应字段及样例。 | | `GET /all/flights` | 无已定义的请求字段;从 Redis 投影读取当前全部动态航班,不含共享航班,与网页客户端同源(`US-12`)。 | 返回查询到的全部航班,不分页。 | Redis 异常时返回错误,不能返回空列表伪装成功。 | 航班字段与类型、集合外层结构、状态码和错误响应样例。 | 旧系统线索(来源:旧项目用户故事「HTTP 接口清单」「日计划请求」): - 三个接口共用 `ResponseDto`,字段为 `is_success`、`err_code`、`err_msg`、`body`。 - `POST /cminmsgs/send` 的成功 `body` 是 `CMINMSGS_ID`,样例为 `{is_success: true, body: }`。 - `GET /all/flights` 的 `body` 是非共享航班的 `SCHD.FLTR` 列表。 - `POST /schd/sync` 的请求体是 `{startDate, endDate}`,时间格式 `yyyy-MM-dd hh:mm` 用无 AM/PM 的 12 小时制。 - 出站报文用 `TYPE=RQFD`、`STYP=NONE`、`SNDR=OSH5`,日期范围编码为 `RQFD.STDB` / `STDE`。 这些字段是否沿用、时间改用何种无歧义格式,都要核对后定稿。 新版日计划是 AODB 当前时刻的完整航班列表(`US-07`),请求是否仍带日期范围由这条全量语义判断。 ## 入站报文与请求应答 AODB 经 CIIMS adapter 把 XML 报文写入 `CMINMSGS`,格式以架构指定的 [SIS 接口规范](../legacy/SIS_AODB_RMS-V0.1.md) 与 [XSD](../legacy/unisysaodbsis.xsd) 为依据。 入站报文按类型处理:`ADFT` 建立计划外航班,`FLOP` 改航班动态,`FDEL` 删航班,`SCHD-DNLD` 与 `SCHD-RESP` 同步日计划快照,参考数据写入 `REF_MASTER`(`US-04`~`US-07`、`US-13`);报文不合法进死信,合法但本系统不支持的类型跳过留档并按已处理写回信箱(`US-03`)。 | 环节 | 已确定的边界 | 尚需确定 | |---|---|---| | 出站请求 | 本系统只发 `RQRD` 参考数据请求与 `RQFD` 日计划请求,经 `COUTMSGS` 落信,交付承诺止于落信(`US-09`;架构「系统定位与范围」「主流程」)。 | 报文类型与子类型清单、发送方取值、时间与序号的构造规则。 | | 在途与作废 | `RQRD` 与 `RQFD` 各自同时最多一条已落信、未结案的请求;同一子类型发新请求时旧请求作废,新请求登记为待发送,等同一报文类型的在途请求收到应答、失败或超时后再落信;请求超过时限未等到应答标记超时(`US-09`)。 | 超时的时限取值。 | | 应答匹配 | 应答按报文类型对应到等待中的请求;AODB 发错或迟到的应答不更新数据,记录后跳过(`US-09`);`SCHD-RESP` 只在请求未过期时生效,迟到的应答不更新数据(`US-07`)。 | 请求与应答的对应字段、过期判定的依据字段。 | | 错误回报 | 收到 `EROR` 时定位到本系统发出的请求,标记失败并告警(`US-09`)。 | `EROR` 与请求的对应字段。 | ## Kafka | 主题 | 已确定的消息语义 | 尚需确定 | |---|---|---| | `msg` | 单条航班变更通知;航班动态与删除处理完成后投递;发送失败自动重试,一直失败的记录保留可查并告警(`US-08`);同一 `FLID` 的变更保序,对外按至少一次投递。删除通知的来源有三处:`FDEL` 删除(`US-06`)、日计划快照缺席删除(`US-07`)、历史清理在物理删除前必要时登记(架构 `D1`)。 | Kafka key、value 的字段与类型、变更和删除的区分方式、版本与去重标识(`Q19`;可用依据是航班当前态的版本规则,见 `FLIGHT_SCHD` 行)、编码方式、分区规则、消费者处理重复和乱序的规则。 | | `schd` | 定时批量发送最新航班状态;发送失败自动重试;对外按至少一次投递。 | “批量”对应的 Kafka record 粒度、key/value 字段与类型、删除航班的表达方式、批次边界、编码方式、消费者去重规则。 | 旧系统线索(来源:旧项目用户故事「前端通知」「动态类(FLOP-*)处理」): - `msg` 的 value 是 `MSG` 的 JSON,含 `META` 与对应业务体;日计划到达通知只有 `META`。 - 只对非共享航班的变更单条下发,共享航班随主航班下发;例外是删除,共享航班被删时也单独发一条 `msg` 删除消息。 - `schd` 把窗口内航班组成 `SCHD.FLTR` 数组 JSON,队列为空时不发送。 跨航班顺序不构成契约。 测试环境须使用独立的数据库、Redis 与 Kafka 主题,且不连接生产信箱(`OPS-3`)。 ## 存储读写边界 ### 共享 MySQL:外部信箱 | 表 | 本系统的操作 | 需要对接方提供的物理契约 | |---|---|---| | `CMINMSGS` | 按信箱编号升序、分批读取未处理的报文,扫描与回写用同一处理时间列;兼容 HTTP 入口写入 XML 原文;处理完成后写入处理完成时刻,只填空值、不覆盖已有值;写回失败由后台任务重试,一直写不上的记录保留在案并告警(`US-01`、`US-02`、`US-10`)。 | 表 DDL、信箱编号与报文原文字段、处理时间列的列名和允许值、该列与对接方所称处理标记是否为同一列、各列类型与可空性、写入必需列、原文保留期和索引;信箱编号按到达顺序单调递增、不复用、不回退的保证(架构「必须保持的约束」)。 | | `COUTMSGS` | 写入 `RQRD` 参考数据请求与 `RQFD` 日计划请求;CIIMS adapter 消费。交付承诺止于请求落信;写入结果不明时记录并告警,不直接重发(架构「主流程」)。 | 表 DDL、请求原文字段、写入必需列、编号生成方式、ACK/错误列的写入责任、重复落信的识别规则。 | 共享 MySQL 归 CIIMS adapter 方所有;本系统不建表、不改表结构、不清除数据,也不写共享历史表。外部表的物理字段必须以对接方提供的现行 DDL 与读写样例核对,不能由本文件推造。 旧项目用户故事「数据表列清单」提供以下**旧系统实体映射列名**,不是现场 DDL、可空性或写权限的证明: | 表 | 旧系统实体映射列名 | 旧系统写入线索 | |---|---|---| | `CMINMSGS` | `CMINMSGS_ID`、`CMINMSGS_CLOB_MSG`、`CMINMSGS_DATE_RECEIVED`、`CMINMSGS_DATE_PROCESSED`、`CMINMSGS_STATUS`、`CMINMSGS_SUBSYSTEM_DATE_SENT`、`CMINMSGS_SUBSYSTEM_NAME`、`CMINMSGS_SUBSYSTEM_SEQUENCE`、`CMINMSGS_SUBSYSTEM_SUBTYPE`、`CMINMSGS_SUBSYSTEM_TYPE` | 兼容入口写原始 XML 与接收时间,处理时间为空;旧系统的扫描与回写都落在 `CMINMSGS_DATE_PROCESSED`(旧项目用户故事「术语与数据语义」);新版必须先按 `US-02` 校验 XML。 | | `COUTMSGS` | `COUTMSGS_ID`、`COUTMSGS_ACK_DATE_RECV`、`COUTMSGS_ACK_REQD`、`COUTMSGS_ACK_RESEND_TIMES`、`COUTMSGS_CLOB_MSG`、`COUTMSGS_DATE_INSERTED`、`COUTMSGS_DATE_SENT`、`COUTMSGS_ENCRYPT`、`COUTMSGS_ERROR`、`COUTMSGS_FINAL_GROUP_IND`、`COUTMSGS_GROUP_ID`、`COUTMSGS_GROUP_ORDER`、`COUTMSGS_NO_MESSAGES`、`COUTMSGS_TRUEFALS_GROUP`、`ROUTINGID` | 旧 `/schd/sync` 写报文 XML、插入时间与 `ROUTINGID=OSH5RQFD`;ACK/错误列的写入责任仍未确认。 | ### Redis:航班查询投影 | 存储 | 承载内容 | 边界 | 尚需确定 | |---|---|---|---| | Redis | 航班查询投影 | 只作查询,不是权威,也不存处理状态;只由本系统写入和移除,网页客户端与 `GET /all/flights` 读同一份,内容来自自有 PostgreSQL 的航班当前态;写投影成功、删除时移除成功,才算对应消息处理完成(架构「数据归属与一致性」;`US-05`、`US-06`)。 | key 与 value 结构及序列化方式、网页客户端读取约定(`Q20`)、每次处理后刷新哪些航班。 | 旧系统线索:投影是 Redis hash `flightInfo`,field 为 `FLID`、value 为 `SCHD.FLTR` 的带类型 JSON(旧项目用户故事「Redis key 汇总」「术语与数据语义」)。 ### 自有 PostgreSQL:内部存储与 admin-api 只读 | 表或表组 | 边界 | 尚需确定的字段级契约 | |---|---|---| | `REF_MASTER` | 静态参考数据与资源状态按类别、编号保存在独立数据表,admin-api 直接只读;新消息覆盖旧记录,全量消息整体替换,增删改消息逐条处理(`US-13`);一类校验不通过只停这一类、其他类照常,校验失败类别的已有记录不变;字段为空表示「当前没有值」,不是删除(架构「必须保持的约束」)。 | 类别和编号的物理列、各类别字段及类型、主键/唯一键、空值在列中怎样保存、写入后何时可读。类别范围与消息中的识别标签见下表。 | | `FLIGHT_SCHD`、资源明细表、`FLIGHT_ROUTE_POINT` | 航班当前态的唯一权威;`FLID` 唯一,已写入非空的运营日不可改,每次成功写入版本号加一、重复消息不重复加(架构「必须保持的约束」);Redis 和 Kafka 从处理结果派生,不反向覆盖这些表。 | 主键、字段与类型、资源明细表清单、外键/索引、版本字段的物理列与迁移 DDL。 | | `PROC_STATE`、`MSG_EVENT`、`REQ_TRACK`、`SCHD_SNAP_LOG`、`PIPELINE_LOCK`、`UNMAPPED_FIELD` | 管道处理、待发事件、请求跟踪、留痕、互斥及未映射字段由本系统维护;不对外提供直接读写接口。 | 字段、约束、索引与迁移 DDL 由内部实现设计确定;若其他系统需读取,须另立读取契约。 | 自有 PostgreSQL 的物理表结构由本系统的迁移 DDL 定稿。生产环境若改用 Oracle 11g,字段类型与迁移方案需先完成适配验证。 ### 静态参考数据类别与编号来源 类别码与识别标签来自架构引用的 [SIS 接口规范](../legacy/SIS_AODB_RMS-V0.1.md);识别同一条参考记录时,用类别码加识别标签值。标签值的格式、标签在哪个范围内唯一,以及保存到 `REF_MASTER` 的方式,仍需在本系统的表结构中明确。 | 类别码 | 类别 | 消息中的识别标签 | SIS 依据 | |---|---|---|---| | `COUL` | 国家代码 | `COUC` | 「AODB country codes event」 | | `ARPT` | 机场代码 | `ITCD` | 「AODB airport codes event」 | | `AIRL` | 航空公司代码 | `ITOP` | 「AODB airline codes event」 | | `AIRC` | 机型代码 | `ITAT` | 「AODB aircraft codes event」 | | `REGN` | 注册号 | `RNUM` | 「AODB registration codes event」 | | `ORGN` | 机构代码 | `OGID` | 「AODB organization codes event」 | | `FLTL` | 航班类型代码 | `FTYP` | 「AODB flight type codes event」 | | `TLST` | 航站楼代码 | `TCOD` | 「AODB terminal codes event」 | | `GLST` | 登机门代码 | `GCOD` | 「AODB gate codes event」 | | `SLST` | 机位代码 | `SCOD` | 「AODB stand codes event」 | | `CLST` | 值机柜台代码 | `CCOD` | 「AODB check in counter codes event」 | | `BLST` | 行李转盘代码 | `BCOD` | 「AODB carousel codes event」 | | `CHLT` | 行李滑槽代码 | `CCOD` | 「AODB chute codes event」 | 资源状态是第十四类消息,类别码为 `RSTA`(SIS 接口规范「AODB resource status event」),识别一条资源状态时须同时使用资源类型 `RTYP` 和资源编号 `RSID`;`CLST` 与 `CHLT` 都使用 `CCOD` 标签,因此不能脱离类别码识别记录。 ## Elasticsearch 航班历史写入 | 契约项 | 已确定的边界 | 尚需确定 | |---|---|---| | 写入对象 | 满足 `US-14` 已结束判据的航班从自有业务数据库写入 Elasticsearch 历史库,作为历史查询副本。 | 历史索引名称、文档 ID、写入字段及类型、嵌套资源结构、字段缺失与删除状态的表达方式、索引保留期与容量上限(架构「数据归属与一致性」列为未定)。 | | 成功确认 | 只有该航班的历史写入成功,才允许从实时数据物理删除;删除前按 `D1` 必要时登记待发删除事件。 | Elasticsearch 写入响应中何种结果算成功、成功是否要求可查询、批量响应如何逐项确认。 | | 写入粒度 | 单个航班写入失败不影响其他航班。 | 使用逐条请求还是批量请求、批量大小、部分成功时的确认与继续处理规则。 | | 失败与重试 | 写入失败的航班保持在实时数据中,下次运行再试;已写入的航班不重复写入;正在被消息处理的航班跳过,下轮再处理。 | 超时或响应不明时的对账方式、可重试错误分类、重试间隔、文档 ID 和覆盖策略如何保证幂等。 | 旧系统线索:逐航班按 `SODT + FLID` 查询旧索引 `flight_hts`,存在则更新、不存在则新增;写入内容是 `SCHD.FLTR` 序列化后的 JSON,单条写入失败跳过该航班(旧项目用户故事「动态航班转历史」)。 ## 待决事项 由本系统与需求方确定的事项见 [specification.md](../specification.md)「本系统与需求方待决」(`Q17`~`Q19`)。 ## 定稿所需证据 1. 核对三个 HTTP 接口的旧系统线索,取得成功和失败响应样例、实际状态码及 `/schd/sync` 的无歧义时间格式。 2. 运营航班显示界面的 `msg`、`schd` 消费样例和字段要求,特别是变更、删除、重复投递的处理方式。 3. CIIMS adapter 方提供的 `CMINMSGS`、`COUTMSGS` 现行 DDL、读写样例和写权限说明,核对旧系统实体映射列名,并确认信箱编号单调递增、不复用、不回退。 4. 13 类参考数据与资源状态的编号规则,以及自有 PostgreSQL 的迁移 DDL。 5. Redis 投影的 key 与 value 结构、序列化方式及网页客户端读取约定。 6. AODB 应答与 `EROR` 样例,含请求与应答的对应字段、超时判定依据。 7. Elasticsearch 历史索引映射、文档样例、逐条或批量写入响应、索引保留期与容量上限,以及写入结果不明时的对账规则。 只有上述证据核对完成后,待定字段才能转为字段级契约;任何新增字段、默认值或错误码都需写明其来源与对接方。