diff --git a/docs/spec-boundary-closure.md b/docs/spec-boundary-closure.md index e3625f5..033249e 100644 --- a/docs/spec-boundary-closure.md +++ b/docs/spec-boundary-closure.md @@ -1,97 +1,51 @@ -# 精简实施方案 +# 需求边界闭合方案 -## 1. 本轮目标 +## 1. 目标 -关闭以下缺口: +阶段 A 闭合 `US-01`~`US-14`、`OPS-1`~`OPS-4`;`US-15` 保留为阶段 B 边界。 -1. `[G-KAFKA-D3]`:生产者配置满足 `D3`。 -2. `[G-IGNORE]`:`US-04` 定义的忽略报文正常终结。 -3. `[G-EVENT-RETENTION]`:已确认投递的事件不会无限增长。 +- 需求与验收以 `US-xx`、`OPS-x` 为唯一依据,本文件只做实施覆盖映射。 +- 实现必须遵守 `D1`~`D4`、`PRE-1`~`PRE-8`、`INV-1`~`INV-22`、`CLM-3`~`CLM-10`、`C-1`~`C-29`。 +- 参数、指标和错误分类只引用 `PARAM:` 与 `reference.md`,不重复取值。 +- `Q2`~`Q16` 未定案时只阻断对应验收,不补写猜测。 -依赖约束仅引用:`D3`、`INV-7`、`INV-8`、`INV-9`、`INV-10`、`US-03`、`US-04`。 +## 2. 边界 -## 2. 明确不做 +- 航班当前态只存自有 PG;不引入 Redis、阶段 A 的 ES、新业务库、并行主泵或分布式锁。 +- 共享 MySQL 只做契约内读写与回填;不建表、不增列、不迁移、不写共享历史表(`C-14`)。 +- 生产保持单活动实例;不承诺端到端恰好一次、跨 `FLID` 顺序或未经验证的 Oracle 11g 支持。 +- `US-15` 未启用前遵守 `D1`:历史写入未确认成功时航班清场删除 0 条。 +- 进度与排期只记 Plane,本文件不记录完成状态。 -本轮不实现: +## 3. 需求覆盖 -- `[G-BACKFILL-BACKOFF]`:没有真实调参需求,保留现有退避算法。 -- `[G-PROC-HST]`、`[G-HST-RETENTION]`:等待 `Q6`、`Q7`、`Q9` 定案后单独设计。 -- `[G-FLOP-IDEMPOTENT]`:继续保持 `INV-20`、`CLM-3` 不可声明。 -- `[G-REQ-TRACK]`、`[G-MAFL]`、`[G-REPLAY-CHANNEL]` 等其他缺口。 +| 需求 | 必须闭合的能力 | 约束 / 缺口锚点 | +|---|---|---| +| `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`、`[G-IGNORE]` | +| `US-05` | ADFT、FDEL、29 类 FLOP、完整航班态及主/共享关系 | `INV-11`~`INV-22`、`Q8`、`Q13`、`Q14`、`Q16`、`[G-FLOP-IDEMPOTENT]`、`[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`、`[G-KAFKA-D3]`、`[G-EVENT-RETENTION]` | +| `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`、`[G-BACKFILL-BACKOFF]`;`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` | 21 类参考主数据完整校验、原子发布、失败保旧 | `Q8` | +| `US-14` | 机位/登机桥映射原子发布,PSDT 只读计算 | `Q8` | +| `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` | -具体排期只记录在 Plane,不写入本 spec。 +## 4. 统一验收 -## 3. [G-KAFKA-D3] - -实现: - -- 将 Kafka producer 的有效 `PARAM:kafka.producers.default.max-in-flight-requests-per-connection` 固定为 `D3` 要求值。 -- 启动时检查最终生效配置;不满足 `D3` 时拒绝启动。 -- 不改变现有投递模型、批次、重试或 topic。 - -验收: - -- 默认配置可以启动。 -- 非法环境变量覆盖导致启动失败。 -- `acks`、幂等和 `max-in-flight` 三项联合满足 `D3`。 - -## 4. [G-IGNORE] - -实现: - -- 继续使用现有 XML 解码结果和 `MsgKind.Unsupported`,不增加新的领域类型或规则引擎。 -- 在 `MessageProcessor` 中按以下顺序处理: - - 解码 META - → 绑定 `IDENTITY_KEY` - → 匹配 `US-04` 忽略清单 - → 命中则写 `SKIPPED` + 回填意图 - → 未命中则进入现有 `MsgKind` 分派 - -- 忽略终态不取得 `PIPELINE_LOCK`,不写航班表,不创建 `MSG_EVENT`。 -- 使用 `LAST_ERROR=ignored:` 保存原因。 -- 只增加 `US-04` 要求的忽略计数;指标名登记到 `reference.md`。 - -验收: - -- `US-04` 中全部规则及大小写场景均命中。 -- 忽略消息先完成身份绑定(`US-03`)。 -- 重复身份继续走既有 `duplicate-of` 路径。 -- `SKIPPED` 与回填意图同语句落库。 -- 不产生航班或 outbox 副作用。 -- 未命中的合法类型继续按 `UNSUPPORTED` 处理。 - -## 5. [G-EVENT-RETENTION] - -实现: - -- 下一条 PG Flyway 迁移仅给 `MSG_EVENT` 增加可空 `SENT_AT`。 -- 所有投递确认操作在设置 `STATE='SENT'` 的同一条 `UPDATE` 中写入 `SENT_AT`。 -- `KAFKA:schd` 新代次重置为 `PENDING` 时清空 `SENT_AT`。 -- 迁移时将存量 `SENT` 行的 `SENT_AT` 设置为迁移时刻 `CURRENT_TIMESTAMP`,避免提前清理。 -- 在现有 `JobRunner` 维护周期中增加一次有界清理,不新增线程或调度参数。 -- 只删除同时满足以下条件的行: - - ``` - STATE = 'SENT' - AND SENT_AT IS NOT NULL - AND SENT_AT < 当前时间 - PARAM:msgx.pipeline.event-retention - ``` - -- 删除仍携带 `STATE='SENT'` 条件,避免与 `KAFKA:schd` 新代次 upsert 竞态。 -- `PENDING`、`DEAD`、`SENT_AT IS NULL` 一律保留。 - -验收: - -- 投递确认与 `SENT_AT` 原子写入。 -- 存量 `SENT` 行迁移后不会立即过期。 -- 到期 `SENT` 行被分批清理,未到期及其他状态不受影响。 -- `KAFKA:schd` 重置与清理两种并发顺序均不误删。 -- 清理可重复执行,不影响投递顺序。 - -## 6. 测试约束 - -- 时间测试统一使用 `TestClocks.kt`。 -- 仓储行为使用内存适配器;迁移结构使用既有 Flyway 测试设施。 -- 禁止 `Thread.sleep` 和真实外部基础设施。 -- 只补上述三个缺口对应的回归,不扩展其他功能矩阵。 +- 每个 PR 标明 `US-xx/验收条目`、相关 `Q`、迁移、配置、恢复影响和未包含范围。 +- 排序、重试、幂等、投递必须覆盖 `invariants.md` 的验证映射;业务类型必须有 golden 样例。 +- 时间测试使用 `TestClocks.kt`;领域与适配器测试使用内存实现,事务与迁移使用既有 PG 测试设施。 +- 自动化测试禁止 `Thread.sleep` 和真实外部基础设施;Kafka/MySQL 现场验收单独留证。 +- 使用锁定的 JDK 25、Micronaut 5.1.3 及现有 KSP/Jackson 编译参数,不升级或重构无关模块。 +- 真实适配器、契约、测试及对应 `OPS-x` 未闭合时,不得宣称需求或生产切流完成。