18 KiB
msgexchange-v2 用户故事草案
依据
architecture.md、design.md、Plane ACM2-3/5/6/7/12/15~22 与 legacy 基线整理。 本文描述目标能力和明确保留的兼容行为,不代表当前代码已完成。
1. 约定
- “信箱已落信”“PG 已入队”“业务处理成功”“共享信箱已回填”“下游已投递”是不同事实。
KEEP表示兼容现役;FIX表示修复 legacy 缺陷;DEFERRED表示不属于阶段 A。- 依赖只表示前置能力,不形成循环;待决策内容不得伪装成验收标准。
2. 阶段 A 用户故事
US-01 可靠采集共享信箱报文
作为 平台运维人员,我希望 持续采集 CMINMSGS 未处理报文,以便 上游无需改变投递方式。
验收标准
- 按配置周期、ID 升序和有限批次采集
DATE_PROCESSED IS NULL;这里只采集入队,不代表业务已处理。 - 快路径使用持久化高水位增量扫描;另以受控周期补偿重扫“未处理且 PG 无状态”的记录。水位只在本批入队确认后推进。
- 每个 ID 在 PG 至多一个
PROC_STATE(PENDING);重复发现不重复入队。 - PG 不可用时不改共享信箱标记;恢复后补偿重扫能补建遗漏状态。
- 单条异常和数据库故障可观察,轮询线程不得静默退出。
依赖:共享库读权限、字段与索引契约。
实现差距:当前 InboxPoller 固定 afterId=0 全量扫描,无持久化水位和独立补偿频控。
US-02 通过兼容接口注入报文
作为 联调人员,我希望 通过 POST /cminmsgs/send 注入 XML,以便 执行回放和对拍。
验收标准
- 信箱落信后返回
CMINMSGS_ID,响应不得暗示 PG 已入队或业务已处理。 - 落信成功但 PG 入队失败时,由 US-01 最终补建。
- Content-Type 支持
text/xml、application/xml与text/plain(默认按 UTF-8 解码);空报文、超大报文(> 10MB)及畸形 XML 返回规范错误。 - 响应结构逐字兼容 legacy
ResponseDto:成功返回{"is_success": true, "body": <CMINMSGS_ID>},失败返回{"is_success": false, "err_code": "<code>", "err_msg": "<detail>"}。 - 生产默认沿用现役内网互信免密姿态(网关限定内部 IP 网段与审计);外露或跨网络时启用 Header 认证。
依赖:US-01。
US-03 严格按序且幂等地执行处理管道
作为 航班数据消费者,我希望 报文严格按信箱顺序处理,以便 重试不会造成倒序状态。
验收标准
- 选择最小未完成 ID;
PENDING、FAILED都占队头,退避期间后续消息不得越过。 - identity 首绑为
SNDR|TYPE|STYP|SEQN;冲突转SKIPPED并记录原 ID。 MALFORMED直接 DEAD;CODEC_ERROR/UNSUPPORTED/INFRA退避;attempts 或 HOL deadline 耗尽后转DEAD(EXHAUSTED)。- PUMP_JOB 不与消息形成统一全序,只在无队头或队头尚在退避窗口时执行;不得让已到期消息饥饿。
- Redis 先应用;
MSG_EVENT与PROC_STATE→SUCCEEDED在同一 PG 事务提交。 - Redis 已写、PG 未提交的窗口可幂等重放。
依赖:US-01。
既有基线定案:生产幂等键默认采用 SNDR|TYPE|STYP|SEQN,include-day-boundary=false 禁开,防止跨日重放漏判;HOL deadline 起算时间统一固化为 PROC_STATE.CREATED_AT(稳定入队时间戳),消除重试刷新 updatedAt 导致的超时不可达缺陷。
US-04 忽略非业务报文(KEEP)
作为 运维人员,我希望 已确认无需处理的报文被明确忽略,以便 不产生 DLQ 噪声。
验收标准
- 解码 META 后、查 Handler 前,大小写不敏感匹配
TYPE-STYP与TYPE-*。 - 基线为
LDM-*、REGN-*、RSTA-*、EROR-*;统一采用EROR,消除 test 的ERROR漂移。 - 命中后进入
SKIPPED,记录ignored:<rule>,不创建业务事件。 - 按 US-09 的规则回填共享信箱,并保留审计计数。
依赖:US-03、US-09。
US-05 应用 ADFT 与 29 类 FLOP 报文
作为 OMMS 业务,我希望 正确应用增量报文,以便 Redis 动态符合 wire 契约。
验收标准
SCHD-ADFT和 29 个 FLOP 子类型均有纯函数 Handler;未知类型进入FAILED(UNSUPPORTED)。- 每类覆盖输入、Redis 变化、msg、schd、处理终态五面断言。
- 航班不存在按 legacy KEEP 语义结束且不重试:以
SUCCEEDED终态结束,按 US-09 回填共享信箱DATE_PROCESSED = now(),STATUS = 'SUCCESS',防止死循环。 - 共享航班默认不直接发通知,而是更新并通知主航班;FDEL 例外定案:删除共享航班时更新主航班 MAFL 列表并发出主航班通知;若删除主航班则删除其及所有子共享关联并发出删除通知;目标航班不存在时幂等成功退出。
- ADFT/FDEL 使用值相等比较,主/共享关系作为一次原子 Redis 变更持久化(FIX)。
- PSDT 依赖 US-14,Handler 不直接调用 admin-api。
依赖:US-03、US-14、SIS/XSD 与 KEEP/FIX 矩阵。
US-06 导入 RESP/DNLD 日计划快照
作为 航班计划使用方,我希望 RESP 与 DNLD 共用快照流程,以便 主动下载和请求应答获得相同终态。
| 报文 | SnapshotFlow | REQ_TRACK | Kafka msg | 迟到/无匹配处理 |
|---|---|---|---|---|
SCHD-DNLD |
是 | 不更新 | 成功后通知 | 不适用(广播/全量) |
SCHD-RESP |
是 | 匹配开放 RQFD 后 DONE | 成功后通知 | 严禁更快照,转 SKIPPED 并审计 |
SCHD-ADFT |
否,走 US-05 | 不更新 | 按增量规则 | 增量应用 |
验收标准
- RESP/DNLD 共用 staging 流式整包校验和 SnapshotFlow,不作为普通 FLOP 增量 Handler 重复实现。
- 主泵执行先后严格服从 I2(happens-before):主泵线程先执行 Redis Lua 完成写新代、旧代差集删除及 generation 版本 CAS(ADFT 航班存活,FIX);Redis 执行成功后进入自有 PG 本地事务。
- 自有 PG 本地事务原子性:同一 PG 事务内原子提交
PROC_STATE → SUCCEEDED、匹配开放请求的REQ_TRACK → DONE(记录 completed_at 与 resp_cminmsgs_id)及MSG_EVENT出站通知。 - 整包失败保留旧快照;相同报文重放(CAS 版本一致)幂等,不重复增代或差删。
- 迟到(
dttm < req.sentAt)或无匹配/过期(EXPIRED)RESP 严禁更新快照,转入PROC_STATE → SKIPPED并记录审计与告警,防止历史快照时光倒流覆盖新状态(对齐 G12)。 - 覆盖首次/连续发布、DNLD→ADFT→DNLD′、RESP 匹配和崩溃窗口。
依赖:US-03、US-08、Redis gen 协议。
US-07 可靠、有序地投递 Kafka
作为 Kafka 消费者,我希望 状态可见后有序投递,以便 通知不指向旧状态。
验收标准
KAFKA:msg按 EVENT_ID FIFO,确认后才标 SENT。KAFKA:schd按周期和上限领取;同一 FLID 仅发批内最新事件。- 失败保持队头并退避;耗尽后 DEAD,不静默丢弃。
- 事件包含稳定去重标识,分区键和重复投递有契约测试:
KAFKA:msg以SNDR作为分区键;KAFKA:schd严格以FLID为分区键,确保单航班有序。 - 生产环境对接 Kafka 2.8+ / 3.x+,生产者强制
acks=all、enable.idempotence=true与max.in.flight.requests.per.connection=1,严禁非幂等降级;投递失败退避重试,达上限转DEAD(DLQ)告警,绝不静默丢弃。
依赖:US-03、现网 Kafka Broker API 版本确认(切流前 kafka-broker-api-versions.sh 探测 InitProducerId(22);未确认前不得标 US-07 实施完成)。
US-08 发起并跟踪 15 类 AODB 请求
作为 业务或运维人员,我希望 发起请求并跟踪生命周期,以便 区分登记、落信、等待、完成和超时。
验收标准
- 支持 14 类 RQRD 参考请求和 1 类 RQFD-NONE 日计划请求。
- REQ_TRACK 先登记;COUTMSGS 落信后才关联 ID 并标 SENT,落信不等于对方已发送。
- 逐类超时与并发规则定案:同类请求并发严格为 1(新请求注册时强制同类未决请求转
EXPIRED);RQFD-NONE超时为 60s,14 类RQRD超时默认为 30s。 - 响应经 US-01/US-03 入站:优先以报文回显
SEQN(echoSeqn)精确匹配开放请求;无回显时降级为时序判定(仅接受DTTM >= SENT_AT的开放请求),并在完成时同 PG 事务标DONE。 - 超时或被替代的请求 EXPIRED;迟到响应(
DTTM < SENT_AT)或无匹配响应严禁更新业务状态/快照,转 SKIPPED 并留审计。 - 集成验收:SCHD-RESP 遵循 US-06;14 类响应刷新 REF_MASTER,不与 admin-api 21 类混同。
依赖:US-01、US-03、COUTMSGS 适配器及逐类超时参数。
US-09 补偿回填共享信箱
作为 上游和运维人员,我希望 PG 终态最终反映到共享信箱,以便 未处理积压语义准确。
验收标准
- 解耦与异步执行:主泵 PG 事务(更新
PROC_STATE终态 + 插入MSG_EVENT)内写入持久化回填意图;PG 事务提交后异步触发共享信箱回填,严禁内联同步阻塞等待共享库;回填失败绝不回滚 PG 终态。 - 持久化补偿:未完成或失败的回填由后台补偿任务按指数退避重试;暴露待回填积压量与最老年龄指标,持续失败触发告警。回填 SQL 具备幂等性(
UPDATE CMINMSGS SET DATE_PROCESSED = :now, STATUS = :status ... WHERE CMINMSGS_ID = :id)。 - 各终态回填规则矩阵(单值锁定;库方/legacy 实测前为占位,见 §7-9):
SUCCEEDED:必须回填(DATE_PROCESSED = now(),STATUS = 'SUCCESS',补齐 META 子系统列)。ignore SKIPPED(规则忽略):必须回填(DATE_PROCESSED = now(),STATUS = 'SKIPPED'),防止上游视作未处理积压持续重扫。duplicate SKIPPED(身份键重复):必须回填(DATE_PROCESSED = now(),STATUS = 'DUPLICATE'),确认去重终结。DEAD(毒丸/耗尽/MALFORMED):必须回填(DATE_PROCESSED = now(),STATUS = 'DEAD'),避免共享信箱长期未处理告警或双跑旧系统死循环。运维人工重放基于自有 PG 驱动,不依赖信箱重置。- 非终态(
PENDING、FAILED):绝对禁止回填,保持DATE_PROCESSED IS NULL。
- 影子与双跑隔离:影子实例绝对禁止回填共享信箱;与 legacy 双跑时严格保持单系统持有标记写权。
- 查询和日志分别展示 PG 终态与信箱回填状态。
依赖:US-03、共享库更新权限、共享库 STATUS 值域确认(库方/legacy 对拍)。
US-10 运维重放与故障处置
作为 运维人员,我希望 查询并安全重放失败项,以便 修复故障而不破坏顺序。
验收标准
- 可按记录、错误类和时间查询 attempts、错误及 traceId。
- 仅
CODEC_ERROR/UNSUPPORTED/INFRA/EXHAUSTED可重放;请求含 MALFORMED 时静默跳过该记录,并返回逐项结果。 - 重放清零 attempts/nextAttemptAt,保留错误审计,仍服从 FIFO。
- DEAD、持续回填失败、队列年龄越界产生告警;操作记录操作者、原因、范围和结果。
依赖:US-03、鉴权与审计。
US-11 归档终态入站报文
作为 平台运维人员,我希望 定期归档终态报文,以便 控制信箱规模且不丢未完成工作。
验收标准
- 默认处理接收时间早于 1 天的
SUCCEEDED/SKIPPED/DEAD;保留期可配置为 1~7 天;不迁 PENDING/FAILED。 - 共享库零建表与 DML 最小化定案:严禁向共享 MySQL 写入
CMINMSGS_HST,共享库严格限定为信箱两表(CMINMSGS 读/回填,COUTMSGS 写入);共享 MySQL 自身历史清理交由库方自身 DBA 策略。 - 归档迁入自有 PG:在自有 PostgreSQL 设计
PROC_STATE_HST(及MSG_EVENT_HST)承载历史归档数据。 - 重复执行幂等并记录计数;迁移失败时 fail-closed,不删除源记录。
阶段:A。
US-12 查询实时航班
作为 授权调用方,我希望 查询实时航班,以便 获得与 Redis 权威态一致的数据。
验收标准
- KEEP
GET /all/flights:返回 Redis 当前航班并过滤MAID != NULL的共享航班。 - 固定响应、空结果、排序、分页/大小上限和一致性时点。
- 影子只查询影子 key;接口具备认证、限流和审计。
US-13 刷新 21 类参考主数据
作为 业务组件,我希望 从 admin-api 刷新 21 类数据到 REF_MASTER,以便 使用可审计的本地主数据。
验收标准
- 采用 ACM2-5 清单;admin-api 拉取与 US-08 的 AODB 请求是两个入口。
- 以
(RTYPE,RKEY)幂等 upsert,记录 SOURCE、刷新时间和批次审计。 - 单类失败不发布半批,不破坏上个可用版本;影子默认不主动刷新生产数据。
US-14 提供机位与登机桥数据
作为 PSDT 处理逻辑,我希望 获得机位和登机桥映射,以便 正确计算 abdg。
验收标准
- 保留 ORMS_STAND 与 ORMS_STAND_AIRBRIDGE,和新增 21 类分开统计。
- 通过适配器拉取并缓存;Handler 不直接 HTTP。
- 近机位生成登机桥,远机位或清空时
abdg为空;多桥规则由 golden 固定。 - admin-api 不可用时使用最后可用版本或明确失败,不写不完整缓存。
3. 延后故事
US-15 历史航班清场(DEFERRED)
作为 平台运维人员,我希望 历史写成功后移出实时态,以便 控制 Redis 规模且不丢历史。
- 全系统统一固定基准时区为
Asia/Shanghai(CST, UTC+8)。 - 阶段归属与 ES 边界定案:
HISTORY_SWEEP延后为阶段 B 能力(DEFERRED),阶段 A 永续以 Redis 作为航班动态权威,完全不接入 ES;不作为阶段 A 切流门禁。 - 五条判史规则与 ES 写入留在阶段 B 启用前完成 100% golden 对拍;逐条隔离坏数据;仅历史写成功的 FLID 可由主泵删除。
- 与快照保持单写者串行并记录计数。
4. 上线 Epic
EPIC-OPS 安全运行、影子验证与切流
该范围不能作为一个故事验收,拆为:
- OPS-1 单写者与 fail-fast:第二写实例拒启;生产缺依赖或管道未启用时失败并说明原因。
- OPS-2 可观测性:健康、队列、最老年龄、投递延迟、回填滞后、DEAD 和一致性均有指标/告警。
- OPS-3 影子隔离:独立 PG、Redis 前缀、topic、服务名;禁用真实出站和回填。
- OPS-4 切流回滚:影子连续稳定对拍不少于 7 天;未解释业务字段差异严格为 0;DLQ 积压为 0;MSG_EVENT 最老滞留 < 5s;切流后设立 48 小时观察期,24 小时内支持按 Runbook 平滑一键回滚。
依赖按实际进入上线范围的阶段 A 故事计算,不包含 US-15。
5. Legacy HTTP 工具面
| 端点 | 决定 | 目标口径 |
|---|---|---|
POST /cminmsgs/send |
KEEP | US-02 |
POST /schd/sync |
KEEP,修正 | 24 小时制、非空/区间校验;只承诺 RQFD 落 COUTMSGS |
GET /all/flights |
KEEP | US-12 |
POST /kafka/topics/{name}/msgs |
不进生产 | 若开发仍需,另建工具并限制 topic allowlist |
GET /flights/migrate |
不做 | legacy 一次性 ES 迁移工具 |
6. 详细文档 TODO
| 顺序 | Plane | 文档动作 | 完成条件 |
|---|---|---|---|
| 1 | ACM2-16 | 固定 RESP/DNLD/ADFT 路由 | US-06、design、ACM2-6 一致,迟到/无匹配禁更快照定案 |
| 2 | ACM2-17 | 拆归档与清场并标阶段 | US-11 属 A,US-15 DEFERRED;HST 禁写,自有 PG 归档定案 |
| 3 | ACM2-19 | 增补信箱回填 | 提交后执行、持久化补偿、四终态回填、影子禁写定案 |
| 4 | ACM2-21 | 消除循环依赖并补管道边界 | US-03 仅依赖 US-01,业务例外归 US-05 |
| 5 | ACM2-15 | 增补 ignoreMsg | 规则、终态、回填和拼写确定 |
| 6 | ACM2-18 | 补查询、机位、21 类数据 | US-12~14 与 US-08 分界明确 |
| 7 | ACM2-20 | 声明 HTTP 工具去留 | 五端点均有决定 |
| 8 | ACM2-22 | 吸收评审剩余项 | 水位、依赖、Broker、deadline 一致 |
| 9 | — | 同步 architecture/design/README | 权威口径、索引与阶段表一致 |
7. 开放问题定案结论汇总
- 【已定案·ACM2-17】归档存储目标:共享库 CMINMSGS_HST 严禁写入,共享库严格限定信箱两表;归档目标确认为自有 PG
PROC_STATE_HST。 - 【已定案·ACM2-21】SEQN 重置与时钟锚点:生产默认保持
include-day-boundary=false;HOL deadline 锚点固化为PROC_STATE.CREATED_AT(稳定入队时间戳)。 - 【已定案·ACM2-20/25】compat 接口契约:支持 text/xml、application/xml 与 text/plain;逐字兼容 legacy
ResponseDto(成功is_success+body;失败is_success+err_code+err_msg,不用msg);生产保持内网信任姿态。 - 【已定案·ACM2-21】航班不存在与 FDEL:航班不存在按 KEEP 正常结束且回填信箱;FDEL 共享航班更新主航班 MAFL 并通知,主航班删除清空关联。
- 【已定案·ACM2-16/18】15 类请求生命周期:同类并发严格为 1;RQFD 超时 60s,RQRD 超时 30s;优先 SEQN 回显,无回显退化 DTTM 时序判定;迟到/无匹配禁更快照。
- 【已定案·ACM2-22/23】Kafka 生产契约:强制
acks=all与idempotence=true,分区键按 FLID(schd)/SNDR(msg)固化;严禁非幂等降级;现网 Broker API 版本未确认前 US-07 不得标实施完成;README 不提供生产降级 env。 - 【已定案·ACM2-17】时区与判史边界:统一
Asia/Shanghai时区;HISTORY_SWEEP 延后至阶段 B,阶段 A 不依赖 ES,Redis 永续动态权威。 - 【已定案·ACM2-22】对拍与回滚阈值:影子对拍至少 7 天;业务差异 0 容忍;DLQ 积压为 0;切流后 48 小时保驾、24 小时可平滑回滚。
- 【已定案·ACM2-26】信箱回填 STATUS 值域:
SUCCEEDED→SUCCESS;ignoreSKIPPED→SKIPPED;duplicateSKIPPED→DUPLICATE;DEAD→DEAD(库方/legacy 实测前为占位;若库方禁新值则仅用 legacy 已用集合)。