docs: message-lifecycle 审查修正——消解跨文档冲突、口径归口并登记 Q12

message-lifecycle.md:
- §5.3 日计划改为现行合并语义(缺席不删、缺失保留,引 flight-state §3.1),类型粒度统一 TYPE-STYP
- §5.1 明确两条扫描路径按 ID 区间取行、不以处理标记为谓词;水位定义与 Q2 绑定
- §4 两个缺口改与 design §10 同措辞;§5.2 的 R 构成挂 Q6/Q9,新增 Q12 积压跳过授权
- §6 方案 B 对账补“只补缺失行、标记单调不回退”;删除能力声明标注待 Q9 确认
- §7 改为“尚未实现”、统一 COUTMSGS_* 列名;§11 ID 不断链改为条件式不变量

user-stories.md:US-11 第 4 条限定为“本系统不写共享历史表/不清除外部信箱”;US-01 扫描谓词指向 lifecycle §5.1;US-01/09/11 前置补口径指针;新增 Q12;OPS-2 补积压与最老未处理信龄;Q10 列名统一。

architecture.md:共享 MySQL 红线限定主体;§6 中断恢复表改为指向 message-lifecycle §4;收报步骤补扫描谓词指针。

design.md:水位定义、回填死信处理、维护作业、归档、缺口恢复统一指向 message-lifecycle。

README.md:核对日期更新至 2026-09-10(代码基线 99a0f5f,文档基线 328bbf8);维护规则补规范类文档一档。
This commit is contained in:
windyboy
2026-09-10 09:00:53 +08:00
parent 328bbf88d2
commit ffd3abd655
5 changed files with 48 additions and 49 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
# 设计文档入口 # 设计文档入口
当前实现核对日期:2026-09-09(与代码基线 d53a0a1 一致)。文档中的目标能力不等于已实现;测试通过不等于现场已发布。 当前实现核对日期:2026-09-10代码基线 99a0f5f;文档基线 328bbf8)。文档中的目标能力不等于已实现;测试通过不等于现场已发布。
| 文档 | 唯一职责 | | 文档 | 唯一职责 |
|---|---| |---|---|
@@ -13,4 +13,4 @@
| [legacy/decision-flight-state-history.md](legacy/decision-flight-state-history.md) | 已撤销方案的存档说明;现行规则仍以 `flight-state.md` 为准。 | | [legacy/decision-flight-state-history.md](legacy/decision-flight-state-history.md) | 已撤销方案的存档说明;现行规则仍以 `flight-state.md` 为准。 |
| [SIS 规范](legacy/SIS_AODB_RMS-V0.1.md) / [XSD](legacy/unisysaodbsis.xsd) | 外部协议事实;即使在 legacy 目录仍是兼容依据。 | | [SIS 规范](legacy/SIS_AODB_RMS-V0.1.md) / [XSD](legacy/unisysaodbsis.xsd) | 外部协议事实;即使在 legacy 目录仍是兼容依据。 |
维护规则:架构写约束,设计写机制,故事写目标,Plane 跟踪工作。不要在多份文档复制阶段清单。 维护规则:架构写约束,设计写机制,规范(`flight-state.md``message-lifecycle.md`)写唯一规则,故事写目标,Plane 跟踪工作。不要在多份文档复制阶段清单;同一规则只允许一处定义,其他文档引用章节号
+3 -10
View File
@@ -62,7 +62,7 @@ CIIMS / AODB 等上游
### 收报与处理 ### 收报与处理
1. `InboxPoller` 默认每秒扫描 `DATE_PROCESSED IS NULL` 的信箱记录,在自有 PG 中建立 `PROC_STATE(PENDING)`。重复扫描不能重复入队;入队失败留待重扫。 1. `InboxPoller` 默认每秒扫描 `DATE_PROCESSED IS NULL` 的信箱记录,在自有 PG 中建立 `PROC_STATE(PENDING)`。重复扫描不能重复入队;入队失败留待重扫。目标形态的扫描谓词与水位的唯一口径见 message-lifecycle.md §5.1。
2. 主泵只处理最小未完成 `MSG_ID`。解析报文、绑定业务身份并去重后,分派给 SCHD/FLOP/FDEL/ADFT 处理器。 2. 主泵只处理最小未完成 `MSG_ID`。解析报文、绑定业务身份并去重后,分派给 SCHD/FLOP/FDEL/ADFT 处理器。
3. 在自有 PG 同一事务内(先取 `PIPELINE_LOCK`)保存航班状态变更(`FLIGHT_SCHD` 与明细表)、处理结果、`MSG_EVENT` 待发事件与回填待办预登记。 3. 在自有 PG 同一事务内(先取 `PIPELINE_LOCK`)保存航班状态变更(`FLIGHT_SCHD` 与明细表)、处理结果、`MSG_EVENT` 待发事件与回填待办预登记。
4. 事务提交后,回填共享信箱的处理标记(外部副作用,补偿保障)。 4. 事务提交后,回填共享信箱的处理标记(外部副作用,补偿保障)。
@@ -88,16 +88,9 @@ CIIMS / AODB 等上游
| 存储 | 承载内容 | 职责说明 | | 存储 | 承载内容 | 职责说明 |
|---|---|---| |---|---|---|
| 自有 PostgreSQL | 单行锁 `PIPELINE_LOCK`、处理状态 `PROC_STATE`、待发事件 `MSG_EVENT`、请求跟踪 `REQ_TRACK`、回填待办 `BACKFILL_TODO`、航班当前态 `FLIGHT_SCHD` + 9 张明细表、留痕 `SCHD_SNAP_LOG` | 本系统唯一业务数据库。消息处理、状态推进与待发事件在单事务内原子提交;本地事务只在此库。 | | 自有 PostgreSQL | 单行锁 `PIPELINE_LOCK`、处理状态 `PROC_STATE`、待发事件 `MSG_EVENT`、请求跟踪 `REQ_TRACK`、回填待办 `BACKFILL_TODO`、航班当前态 `FLIGHT_SCHD` + 9 张明细表、留痕 `SCHD_SNAP_LOG` | 本系统唯一业务数据库。消息处理、状态推进与待发事件在单事务内原子提交;本地事务只在此库。 |
| 共享 MySQL | `CMINMSGS` 入站信箱、`COUTMSGS` 出站信箱 | 外部系统所有。仅执行约定的信箱读写处理标记回填,不建表、不迁移 schema、不写历史表。兼容 HTTP 入口可按既有契约写入入站信箱。 | | 共享 MySQL | `CMINMSGS` 入站信箱、`COUTMSGS` 出站信箱 | 外部系统所有。本系统仅执行约定的信箱读写处理标记回填,不建表、不迁移 schema、不写历史表;由库方按 Q9 执行的清除与历史归档见 message-lifecycle.md §6。兼容 HTTP 入口可按既有契约写入入站信箱。 |
**不使用跨库事务。** PG 事务只能保证“处理结果与待发事件一起提交”,不能覆盖 MySQL 回填或 Kafka 发送等外部副作用。跨存储依靠幂等、重试和持久化补偿恢复 **不使用跨库事务。** PG 事务只能保证“处理结果与待发事件一起提交”,不能覆盖 MySQL 回填或 Kafka 发送等外部副作用。跨存储依靠幂等、重试和持久化补偿恢复;各中断位置的判定与恢复动作统一见 [message-lifecycle.md](message-lifecycle.md) §4,本文不重复。
| 中断位置 | 恢复要求 |
|---|---|
| 信箱已有报文,PG 入队失败 | 重扫补建,并按信箱 ID 去重。 |
| PG 提交失败 | 事务原子回滚,无中间态残留;消息重试时整体重放。 |
| PG 已提交,信箱回填失败 | 持久化记录补偿任务并重试回填,不能重新执行已完成的业务处理。 |
| 下游已接收,本地尚未标记发送成功 | 允许重发;下游或出站适配协议必须具备去重能力。 |
对外投递按**至少一次**设计,不承诺端到端恰好一次。Kafka 生产者幂等不能消除应用重启或 outbox 重发带来的所有重复。 对外投递按**至少一次**设计,不承诺端到端恰好一次。Kafka 生产者幂等不能消除应用重启或 outbox 重发带来的所有重复。
+5 -5
View File
@@ -71,7 +71,7 @@ SNDR | TYPE | STYP | SEQN
`InboxPoller` 默认每秒按 ID 升序、有限批次(`claim-batch`,默认 50)读取 `DATE_PROCESSED IS NULL` 的信箱记录,经 `InboxEnqueue` 在自有 PG 建立 `PENDING`;重复扫描幂等,入队失败留待下一轮。收报层不解析业务载荷,也不回填已处理标记。 `InboxPoller` 默认每秒按 ID 升序、有限批次(`claim-batch`,默认 50)读取 `DATE_PROCESSED IS NULL` 的信箱记录,经 `InboxEnqueue` 在自有 PG 建立 `PENDING`;重复扫描幂等,入队失败留待下一轮。收报层不解析业务载荷,也不回填已处理标记。
快路径水位与受控补扫是目标形态,当前`afterId=0` 每轮全量扫描(§10。**水位不是已处理标记,也不能单独证明较小 ID 已收齐**;迟提交、ID 空洞与补扫场景的顺序保证在启用前必须验证。 水位的定义(连续上界、遇空洞即停)、扫描谓词与补偿窗口唯一见 [message-lifecycle.md](message-lifecycle.md) §5.1;水位不是已处理标记,其有效性以 Q2 的 ID 单调承诺为前提。快路径水位与受控补扫是目标形态,当前按 `afterId=0` 每轮全量扫描(§10,迟提交与空洞场景的顺序保证在启用前必须验证。
兼容 HTTP 入口执行“写入共享信箱 → PG 入队”。两步不在同一事务中:信箱成功而 PG 失败时,原文不能丢失,由轮询补建;客户端失败重试可能再次写信箱,业务身份去重仍然必需。 兼容 HTTP 入口执行“写入共享信箱 → PG 入队”。两步不在同一事务中:信箱成功而 PG 失败时,原文不能丢失,由轮询补建;客户端失败重试可能再次写信箱,业务身份去重仍然必需。
@@ -101,7 +101,7 @@ SNDR | TYPE | STYP | SEQN
- 原文缺失归为 `MALFORMED`;读取异常不能伪装成“缺失”,应进入基础设施重试。 - 原文缺失归为 `MALFORMED`;读取异常不能伪装成“缺失”,应进入基础设施重试。
- 忽略规则(`LDM / REGN / RSTA / EROR``SKIPPED`)尚未实现(§10);不能因类型未覆盖就把合法忽略报文当非法报文处理。 - 忽略规则(`LDM / REGN / RSTA / EROR``SKIPPED`)尚未实现(§10);不能因类型未覆盖就把合法忽略报文当非法报文处理。
- 航班变更、待发事件、处理终态与回填待办在同一 PG 事务原子提交;跨存储双写窗口已根除。 - 航班变更、待发事件、处理终态与回填待办在同一 PG 事务原子提交;跨存储双写窗口已根除。
- 终态回填发生在提交后:成功、业务重复与协议拒绝包持有可用 META 并回填;缺 META 或解码失败的死信无法回填,外部处理方式待确认(US-09/Q7)。`PENDING / FAILED` 禁止回填;影子环境禁写。 - 终态回填发生在提交后:成功、业务重复与协议拒绝包持有可用 META 并回填;缺 META 或解码失败的死信不在常规回填范围,按超期补写规则处理([message-lifecycle.md](message-lifecycle.md) §5.2US-09/Q7)。`PENDING / FAILED` 禁止回填;影子环境禁写。
## 4. 日计划快照与请求匹配 ## 4. 日计划快照与请求匹配
@@ -163,7 +163,7 @@ REGISTERED → SENT → WAITING → DONE
`ReplayService` 只允许 `CODEC_ERROR / UNSUPPORTED / INFRA / EXHAUSTED``FAILED / DEAD` 回到 `PENDING`,重置次数与下次执行时间,保留身份与错误审计。它按错误类整批重放,尚无按记录预检、操作审计与管理入口(US-10)。旧消息进入终态后后续消息可能已执行,**重新入队不等于恢复历史顺序**;人工重放前必须评估状态覆盖和版本保护,不能直接批量重放到生产。 `ReplayService` 只允许 `CODEC_ERROR / UNSUPPORTED / INFRA / EXHAUSTED``FAILED / DEAD` 回到 `PENDING`,重置次数与下次执行时间,保留身份与错误审计。它按错误类整批重放,尚无按记录预检、操作审计与管理入口(US-10)。旧消息进入终态后后续消息可能已执行,**重新入队不等于恢复历史顺序**;人工重放前必须评估状态覆盖和版本保护,不能直接批量重放到生产。
**维护作业**`JobRunner` 用独立 daemon 线程每 30 秒触发 `BackfillSweepJob`(回填补偿扫描,指数退避 30 秒起步、封顶 15 分钟),每天机场时区 03:30 后触发一次 `HistorySweepJob`(§6.2)。作业不再经 `PUMP_JOB` 队列插队,不参与消息 FIFO,也不使到期消息饥饿。 **维护作业**`JobRunner` 用独立 daemon 线程每 30 秒触发 `BackfillSweepJob`(回填补偿扫描,指数退避 30 秒起步、封顶 15 分钟),每天机场时区 03:30 后触发一次 `HistorySweepJob`(§6.2)。作业不再经 `PUMP_JOB` 队列插队,不参与消息 FIFO,也不使到期消息饥饿。作业与回填通道的生命周期口径见 [message-lifecycle.md](message-lifecycle.md) §3/§4。
### 6.2 历史清理与归档 ### 6.2 历史清理与归档
@@ -171,7 +171,7 @@ REGISTERED → SENT → WAITING → DONE
**留痕清理**`SCHD_SNAP_LOG` 保留 90 天,在历史清理窗口内按 `(SCOPE_END, RECV_AT)` 删除。 **留痕清理**`SCHD_SNAP_LOG` 保留 90 天,在历史清理窗口内按 `(SCOPE_END, RECV_AT)` 删除。
**处理终态归档**`PROC_STATE_HST` 仍是目标表(user-stories.md US-11),尚未建表;不得归档 `PENDING / FAILED`,也不能因移走身份记录而失去业务去重能力。ES 历史投影(阶段 B)不启用。 **处理终态归档**`PROC_STATE_HST` 仍是目标表(user-stories.md US-11),尚未建表;不得归档 `PENDING / FAILED`,也不能因移走身份记录而失去业务去重能力。ES 历史投影(阶段 B)不启用。自有记录归档与信箱原文保留的关系见 [message-lifecycle.md](message-lifecycle.md) §8/§9。
共享信箱保留策略由库所有方管理;历史写入与删除事件入队之间仍需恢复方案,顺序调用不构成原子提交。 共享信箱保留策略由库所有方管理;历史写入与删除事件入队之间仍需恢复方案,顺序调用不构成原子提交。
@@ -225,7 +225,7 @@ REGISTERED → SENT → WAITING → DONE
以下缺口直接影响上述设计是否成立,不能以类或接口已存在作为完成依据: 以下缺口直接影响上述设计是否成立,不能以类或接口已存在作为完成依据:
- **事务与外部副作用**:状态、事件、终态与回填待办同 PG 事务已实现,回填失败落 `BACKFILL_TODO` 并由 `BackfillSweepJob` 到期重试。剩余缺口在“提交后回填前崩溃”与“待办落账再次失败”两个窗口,不能认定补偿最终必达。 - **事务与外部副作用**:状态、事件、终态与回填待办同 PG 事务已实现,回填失败落 `BACKFILL_TODO` 并由 `BackfillSweepJob` 到期重试。剩余缺口在“提交后回填前崩溃”与“待办落账再次失败”两个窗口,不能认定补偿最终必达;两个窗口的恢复判定见 [message-lifecycle.md](message-lifecycle.md) §4
- **收报与调度**:轮询仍从 `afterId=0` 每轮全量扫描,持久水位与受控补扫未完成;较小 ID 迟提交与空洞场景的顺序保证未验证。滞留判据使用 `updatedAt` 与直取系统时间,未基于稳定起始时刻。 - **收报与调度**:轮询仍从 `afterId=0` 每轮全量扫描,持久水位与受控补扫未完成;较小 ID 迟提交与空洞场景的顺序保证未验证。滞留判据使用 `updatedAt` 与直取系统时间,未基于稳定起始时刻。
- **快照与业务能力**DNLD/RESP/ADFT 与 FLOP/FDEL 处理器、整包校验与跨运营日整包拒绝均已接入;但 RESP 应答守卫与出站请求未实现,忽略规则(US-04)未实现,29 类 FLOP 与参考应答的逐类矩阵未补全,ADFT 缺失字段与 `FLID` 重用语义待上游确认。 - **快照与业务能力**DNLD/RESP/ADFT 与 FLOP/FDEL 处理器、整包校验与跨运营日整包拒绝均已接入;但 RESP 应答守卫与出站请求未实现,忽略规则(US-04)未实现,29 类 FLOP 与参考应答的逐类矩阵未补全,ADFT 缺失字段与 `FLID` 重用语义待上游确认。
- **航班读写**:唯一写入口与权威读已落地;ROUT/ERUT 联合主键、空值/未知属性保真、事件在事务内只算一次、逐航班多次查询仍待修正(见 flight-state.md §6)。`/all/flights` 尚未实现。 - **航班读写**:唯一写入口与权威读已落地;ROUT/ERUT 联合主键、空值/未知属性保真、事件在事务内只算一次、逐航班多次查询仍待修正(见 flight-state.md §6)。`/all/flights` 尚未实现。
+29 -24
View File
@@ -23,7 +23,7 @@
|---|---|---| |---|---|---|
| 落信:报文进入信箱 | `CMINMSGS` 中存在该行 | 上游 | | 落信:报文进入信箱 | `CMINMSGS` 中存在该行 | 上游 |
| 入队:本系统开始处理 | 自有 PG 建立 `PROC_STATE` 记录 | `InboxPoller` | | 入队:本系统开始处理 | 自有 PG 建立 `PROC_STATE` 记录 | `InboxPoller` |
| 处理完成:业务有结论 | `PROC_STATE` 到达终态(SUCCEEDED / SKIPPED / DEAD | 主泵 | | 处理完成:业务处理完成 | `PROC_STATE` 到达终态(SUCCEEDED / SKIPPED / DEAD | 主泵 |
| 已回填:信箱写入处理标记 | 信箱行持有处理标记 | 回填与补偿通道 | | 已回填:信箱写入处理标记 | 信箱行持有处理标记 | 回填与补偿通道 |
| 下游确认:下游已接收 | `MSG_EVENT``SENT` | `delivery`Dispatcher / flushSchd | | 下游确认:下游已接收 | `MSG_EVENT``SENT` | `delivery`Dispatcher / flushSchd |
@@ -43,13 +43,13 @@ MSG_EVENT PENDING ──→ SENT
- `PENDING``FAILED` 是处理中的状态,`FAILED` 继续退避重试并占用 FIFO 队头;`SUCCEEDED / SKIPPED / DEAD` 是终态,到达后队列方可推进。 - `PENDING``FAILED` 是处理中的状态,`FAILED` 继续退避重试并占用 FIFO 队头;`SUCCEEDED / SKIPPED / DEAD` 是终态,到达后队列方可推进。
- `DEAD``FAILED` 不是不可逆:经人工批准,指定错误类别的记录可重新置回 `PENDING` 处理(放行范围见 §9 / design.md §6.1)。重放处理的是当前状态,不恢复历史处理顺序。 - `DEAD``FAILED` 不是不可逆:经人工批准,指定错误类别的记录可重新置回 `PENDING` 处理(放行范围见 §9 / design.md §6.1)。重放处理的是当前状态,不恢复历史处理顺序。
- 航班变更、待发事件、处理终态与回填待预登记四类写入位于同一个 PG 事务,一起提交或一起回滚;信箱处理标记写在该事务之后,依赖 `BACKFILL_TODO` 补偿记录最终写入。 - 航班变更、待发事件、处理终态与回填待预登记四类写入位于同一个 PG 事务,一起提交或一起回滚;信箱处理标记写在该事务之后,依赖 `BACKFILL_TODO` 补偿记录最终写入。
## 3. 处理阶段 ## 3. 处理阶段
| 阶段 | 输入 | 输出 | 幂等依据 | 失败处理 | | 阶段 | 输入 | 输出 | 幂等依据 | 失败处理 |
|---|---|---|---|---| |---|---|---|---|---|
| 收报 | `DATE_PROCESSED IS NULL` 的信箱行 | `PROC_STATE(PENDING)` | `MSG_ID` 主键 | 下轮扫描补入队 | | 收报 | ID 区间内尚未入队的信箱行(谓词见 §5.1) | `PROC_STATE(PENDING)` | `MSG_ID` 主键 | 下轮扫描补入队 |
| 取队头 | 最小未完成 `MSG_ID` | 本批处理消息 | 表状态即队列 | 无队头则等待 | | 取队头 | 最小未完成 `MSG_ID` | 本批处理消息 | 表状态即队列 | 无队头则等待 |
| 解码与身份 | 信箱原文 | `DecodedMessage``IDENTITY_KEY` | 身份唯一约束 | 报文非法→`DEAD`;处理能力不足→`FAILED` 退避 | | 解码与身份 | 信箱原文 | `DecodedMessage``IDENTITY_KEY` | 身份唯一约束 | 报文非法→`DEAD`;处理能力不足→`FAILED` 退避 |
| 事务处理 | 当前完整状态 + 报文载荷 | 航班变更、终态、事件、回填待办 | 消息 ID + 业务身份 | 事务整体回滚重试 | | 事务处理 | 当前完整状态 + 报文载荷 | 航班变更、终态、事件、回填待办 | 消息 ID + 业务身份 | 事务整体回滚重试 |
@@ -72,12 +72,12 @@ MSG_EVENT PENDING ──→ SENT
| 标记写入中途 | 标记仍为空 | 重新写入;重复写入同一值无副作用 | | 标记写入中途 | 标记仍为空 | 重新写入;重复写入同一值无副作用 |
| 下游已接收、`SENT` 未置 | 事件仍 `PENDING` | 允许重发,下游按事件身份去重 | | 下游已接收、`SENT` 未置 | 事件仍 `PENDING` | 允许重发,下游按事件身份去重 |
两个缺口在闭环前不能宣称恢复完整: 两个缺口在闭环前不能宣称恢复完整(口径与 design.md §10「事务与外部副作用」一致)
1. 事务提交后、补偿开始前仍存在崩溃窗口 1. 事务提交后、回填动作开始前的崩溃窗口(提交后回填前崩溃)
2. 补偿重试尚未证明"最终一定完成" 2. 回填待办二次落账失败(待办落账再次失败)
两项登记于 design.md §10(事务与外部副作用)与 user-stories.md US-09。 两项登记于 design.md §10 与 user-stories.md US-09;本表的恢复判定以这两个窗口为前提
## 5. 消费水位、超期补写与历史积压 ## 5. 消费水位、超期补写与历史积压
@@ -92,13 +92,15 @@ MSG_EVENT PENDING ──→ SENT
日常执行方式:快路径从 `ID > W` 起按升序有限批次扫描;另按周期对窗口内可能迟到或空洞的行做补偿扫描。需要区分:水位表示"读取进度",与"已处理标记"是两个事实,不能互相替代。 日常执行方式:快路径从 `ID > W` 起按升序有限批次扫描;另按周期对窗口内可能迟到或空洞的行做补偿扫描。需要区分:水位表示"读取进度",与"已处理标记"是两个事实,不能互相替代。
两条扫描路径都按 **ID 区间**取行,不以处理标记为扫描谓词;标记只用于回填与库方清除,不参与消息发现。否则已入队但尚未回填的行会永久占据批次,这正是 US-01 条目 3 与 Q2 要求排除的场景。
### 5.2 超期标记补写 ### 5.2 超期标记补写
两类信箱行无法通过正常回填获得处理标记:报文残缺且缺少元数据的死信,以及回填通道长期失败的行。处理规则为: 两类信箱行无法通过正常回填获得处理标记:报文残缺且缺少元数据的死信,以及回填通道长期失败的行。处理规则为:
**已达 `PROC_STATE` 终态、且接收时间超期(`DATE_RECEIVED < NOW R`)仍无标记的信箱行,由回填通道补写一个库方认可的"已处理"类标记。** **已达 `PROC_STATE` 终态、且接收时间超期(`DATE_RECEIVED < NOW R`)仍无标记的信箱行,由回填通道补写一个库方认可的"已处理"类标记。**
- 期限 `R` 必须不小于(人工重放期限 + 人工处置期限)之和。提前补写会使仍可重放的消息失去原件资格。 - 期限 `R` 必须不小于(人工重放期限 + 人工处置期限)之和;两项期限的取值口径分别见 Q6 与 Q9,确认前不得下调 `R`。提前补写会使仍可重放的消息先被库方清除、失去原件资格。
- 中间态(`PENDING` / `FAILED`)不适用本规则:处理未完成时不打标,也不允许被清除。 - 中间态(`PENDING` / `FAILED`)不适用本规则:处理未完成时不打标,也不允许被清除。
- 补写值仅限于库方认可的 legacy 值集(Q7);死信、业务重复等内部原因记录在 `PROC_STATE` 与审计日志,不在信箱新增枚举。 - 补写值仅限于库方认可的 legacy 值集(Q7);死信、业务重复等内部原因记录在 `PROC_STATE` 与审计日志,不在信箱新增枚举。
- 补写只针对空标记;已有值不回撤、不覆盖,重复执行无副作用。 - 补写只针对空标记;已有值不回撤、不覆盖,重复执行无副作用。
@@ -109,36 +111,36 @@ MSG_EVENT PENDING ──→ SENT
"历史积压"指信箱中成规模的未处理存量:上线前遗留、停机期间累积、或消量未完成的批次。处理方案分三步,并约束四条行为红线。 "历史积压"指信箱中成规模的未处理存量:上线前遗留、停机期间累积、或消量未完成的批次。处理方案分三步,并约束四条行为红线。
**第一步:摸底。** 处理动作开始前,先确定积压的范围与构成:ID 区间、条数、时间跨度、报文类型分布(SCHD / FLOP / FDEL / ADFT 等),并与库方确认其中哪些仍需业务处理、哪些按约定跳过(跳过基调只在该批确认时成立,值集见 Q7)。 **第一步:摸底。** 处理动作开始前,先确定积压的范围与构成:ID 区间、条数、时间跨度、报文类型分布(`SCHD-DNLD/RESP/ADFT``FLOP-*``FDEL` 等),并与库方确认其中哪些仍需业务处理、哪些按约定跳过(跳过基调只在该批确认时成立,授权与留痕见 Q12,标记值集见 Q7)。
**第二步:先入队,后处理。** 两阶段执行,禁止边收边处理一辆长队: **第二步:先入队,后处理。** 两阶段执行,禁止边收边处理一辆长队:
1. 消化阶段只做入队:`InboxPoller` 按升序有限批次将历史行全部建为 `PROC_STATE(PENDING)`,水位随之推到积压末端。此阶段只写自有 PG,不触碰信箱标记。 1. 消化阶段只做入队:`InboxPoller` 按升序有限批次将历史行全部建为 `PROC_STATE(PENDING)`,水位随之推到积压末端(连续推进以 §5.1 的 Q2 承诺为前提)。此阶段只写自有 PG,不触碰信箱标记。
2. 入队完成后交给主泵按最小未完成 ID 顺序消化。顺序与阈限与日常完全相同:不加速、不分流、不走旁路。 2. 入队完成后交给主泵按最小未完成 ID 顺序消化。顺序与阈限与日常完全相同:不加速、不分流、不走旁路。
这样做的理由:入队是便宜操作(可大批量),处理昂贵操作(解码 + 事务),把两者分开后,入库阶段的中断恢复只涉及重扫(§4 第一行),不会把半处理的事务复杂化;同时水位可以尽早到达完整上界,快路径与补扫窗口立即生效。 这样做的理由:入队廉价、处理昂贵;分开后入队阶段的中断恢复只涉及重扫(§4 第一行),水位也能尽早到达完整上界,快路径与补扫窗口立即生效。
**第三步:等待过程中的四个边界。** **第三步:等待过程中的四个边界。**
- 不插队:主泵按 FIFO 消化,积压期间到达的实时消息排在积压之后。本设计不允许并行队头,也不允许实时通道跳过积压。 - 不插队:主泵按 FIFO 消化,积压期间到达的实时消息排在积压之后。本设计不允许并行队头,也不允许实时通道跳过积压。
- 不失控:队头滞留上限(head-deadline,当前 10 分钟)对积压同样生效;队头长期失败按既有规则转 `DEAD(EXHAUSTED)` 并告警,不会因积压而延长容忍。 - 不失控:队头滞留上限(head-deadline,当前 10 分钟)对积压同样生效;队头长期失败按既有规则转 `DEAD(EXHAUSTED)` 并告警,不会因积压而延长容忍。在 Q6 收敛前,该上限的实际判据仍是 `updatedAt` 与系统取时(见 design.md §10),本条款是目标口径。
- 报文类型的处理方式不变:旧的全量日计划(SCHD-DNLD)按最一份覆盖即可正确收敛,但仍逐条执行;动态增量(FLOP / FDEL / ADFT)持有时序语义,必须逐条。 - 报文类型的处理方式不变:旧的全量日计划(`SCHD-DNLD`)按最一份**合并**即可收敛(缺席不删、缺失字段保留,见 flight-state.md §3.1,但仍逐条执行;动态增量(`FLOP-*` / `FDEL` / `ADFT`)持有时序语义,必须逐条。
- 可放弃但必须留痕:摸底批中经库方确认"不再处理"的行,处置方式为——`PROC_STATE``SKIPPED` 并记录跳过原因,到达终态后走 §5.2 通道补写标记;本方案不支持任何"整段 DELETE"的快速通道。 - 可放弃但必须留痕:摸底批中经库方确认"不再处理"的行,处置方式为——`PROC_STATE``SKIPPED` 并记录跳过原因,到达终态后走 §5.2 通道补写标记;本方案不支持任何"整段 DELETE"的快速通道。
**验收口径**:积压消化期间持续输出三项指标——剩余积压条数、最老未处理信龄、预计消化时长;期间不允许出现 FIFO 越序、身份去重失效或头行滞留超时未告警。红线依据:architecture.md §5(消息严格 FIFO)、单写者约束。 **验收口径**:积压消化期间持续输出三项指标——剩余积压条数、最老未处理信龄、预计消化时长;期间不允许出现 FIFO 越序、身份去重失效或头行滞留超时未告警。红线依据:architecture.md §5(消息严格 FIFO)、单写者约束。三项指标并入 user-stories.md OPS-2 的可观测性验收。
## 6. 信箱数据清除 ## 6. 信箱数据清除
表结构变更与物理清除由库方执行或书面授权执行;本系统对共享 MySQL 不建表、不改结构(红线见 architecture.md §6)。本系统在清除事务中的义务只有一项:为处理完成的行及时写入处理标记,使可清除范围存在明确边界。 表结构变更与物理清除由库方执行或书面授权执行;本系统对共享 MySQL 不建表、不改结构(红线见 architecture.md §6)。本系统不执行 DDL、不写共享历史表:`CMINMSGS_HST` 的历史归档写入由库方执行,属 Q9 授权范围。本系统在清除事务中的义务只有一项:为处理完成的行及时写入处理标记,使可清除范围存在明确边界。
具体方案由库方选择(Q9)。以下两种方案均基于 MySQL 自身能力:支持 `RANGE` 分区与 `TRUNCATE / DROP PARTITION`,不支持 `EXCHANGE PARTITION` 具体方案由库方选择(Q9)。以下两种方案均基于 MySQL 自身能力:支持 `RANGE` 分区与 `TRUNCATE / DROP PARTITION`,不支持 `EXCHANGE PARTITION`(能力与现场版本待库方书面确认,Q9
**方案 A:按日分区(首选)**,适用于库方可以为表增加分区的场合。 **方案 A:按日分区(首选)**,适用于库方可以为表增加分区的场合。
1. `CMINMSGS``DATE_RECEIVED` 建立日粒度 RANGE 分区; 1. `CMINMSGS``DATE_RECEIVED` 建立日粒度 RANGE 分区;
2. 某分区到达保留期时,确认该分区全部行已持有处理标记(§5.2 保证该条件在有限时间内满足); 2. 某分区到达保留期时,确认该分区全部行已持有处理标记(§5.2 保证该条件在有限时间内满足);
3. 将该分区复制入历史表:`INSERT INTO CMINMSGS_HST SELECT``NOT EXISTS` 判重); 3. 将该分区复制入历史表:`INSERT INTO CMINMSGS_HST SELECT``NOT EXISTS` 判重);
4. `TRUNCATE / DROP PARTITION` 执行清除:DDL 级操作,无行锁竞争,页外大字段(`CMINMSGS_CLOB_MSG` 列)整块释放,不产生碎片与 binlog 压力 4. `TRUNCATE / DROP PARTITION` 执行清除:DDL 级操作,无行锁竞争,页外大字段(`CMINMSGS_CLOB_MSG` 列)整块释放碎片与 binlog 影响待现场验证
前提:库方确认现场 MySQL 版本支持分区 DDL,并已授权执行。 前提:库方确认现场 MySQL 版本支持分区 DDL,并已授权执行。
@@ -147,7 +149,7 @@ MSG_EVENT PENDING ──→ SENT
1. `CREATE TABLE CMINMSGS_NEW LIKE CMINMSGS`,并将 `AUTO_INCREMENT` 种子设为 `max(ID) + 1` 1. `CREATE TABLE CMINMSGS_NEW LIKE CMINMSGS`,并将 `AUTO_INCREMENT` 种子设为 `max(ID) + 1`
2. 将保留窗内行(`DATE_RECEIVED ≥ NOW R_keep`)复制至新表; 2. 将保留窗内行(`DATE_RECEIVED ≥ NOW R_keep`)复制至新表;
3. 以单语句原子 `RENAME TABLE` 完成换名; 3. 以单语句原子 `RENAME TABLE` 完成换名;
4. 对账:换名与复制之间新写入及新标记的行,从旧表幂等补回; 4. 对账:换名与复制之间新写入及新标记的行,从旧表补回;只补新表缺失的行,已存在行按标记单调取并集,不回退、不覆盖(§11)
5. 旧表中早于保留窗的部分追加写入 `CMINMSGS_HST``NOT EXISTS` 判重); 5. 旧表中早于保留窗的部分追加写入 `CMINMSGS_HST``NOT EXISTS` 判重);
6. `DROP TABLE` 旧表:秒级完成,碎片与大字段一并释放。 6. `DROP TABLE` 旧表:秒级完成,碎片与大字段一并释放。
@@ -162,14 +164,14 @@ MSG_EVENT PENDING ──→ SENT
## 7. 出站信箱(COUTMSGS ## 7. 出站信箱(COUTMSGS
本系统一侧的规则(实现中:出站适配与请求协调尚未交付,机制描述见 design.md §4.2): 本系统一侧的规则如下(出站适配与请求协调**尚未实现**;请求生命周期的机制目标见 design.md §4.2,本节不重复):
出站前在 `REQ_TRACK` 登记 `REGISTERED`;写入 `COUTMSGS` 并确认落信后置 `SENT` 并关联出站记录 ID。"落信"指写入信箱成功,不等于下游已读取或已发送,交付承诺仅到落信为止(US-08)。 出站前在 `REQ_TRACK` 登记 `REGISTERED`;写入 `COUTMSGS` 并确认落信后置 `SENT` 并关联出站记录 ID。"落信"指写入信箱成功,不等于下游已读取或已发送,交付承诺仅到落信为止(US-08)。
本系统写入的行由谁消费、按什么顺序消费,**当前未知**。以下事项在 Q10 关闭前按未知处理,不得作为已具备能力描述: 本系统写入的行由谁消费、按什么顺序消费,**当前未知**。以下事项在 Q10 关闭前按未知处理,不得作为已具备能力描述:
- 消费方与消费顺序; - 消费方与消费顺序;
- `COUTMSGS_ACK_DATE_RECV / ACK_RESEND_TIMES / DATE_SENT / ERROR` 各列的语义与写入责任; - `COUTMSGS_ACK_DATE_RECV``COUTMSGS_ACK_RESEND_TIMES``COUTMSGS_DATE_SENT``COUTMSGS_ERROR` 各列的语义与写入责任;
- 出站行的清除责任与保留期; - 出站行的清除责任与保留期;
- 落信成功但本地未置 `SENT` 时的重复写入风险及下游去重契约。 - 落信成功但本地未置 `SENT` 时的重复写入风险及下游去重契约。
@@ -185,19 +187,22 @@ MSG_EVENT PENDING ──→ SENT
- 可重放的错误类别为 `CODEC_ERROR / UNSUPPORTED / INFRA / EXHAUSTED` 四类(以 design.md §6.1 为准);重放处理当前状态,不恢复历史顺序。 - 可重放的错误类别为 `CODEC_ERROR / UNSUPPORTED / INFRA / EXHAUSTED` 四类(以 design.md §6.1 为准);重放处理当前状态,不恢复历史顺序。
- 重放的前提是信箱原文仍可读取:`R_keep` 必须覆盖重放期限(§6),属于硬约束。 - 重放的前提是信箱原文仍可读取:`R_keep` 必须覆盖重放期限(§6),属于硬约束。
- 处理时无法读取原文,一律按 `MALFORMED → DEAD` 处理。若原文缺失源于库方违反保留契约提前清除,按契约违例走运维追责通道;该消息的死信处置本身不变。 - 处理时无法读取原文,一律按 `MALFORMED → DEAD` 处理。若原文缺失源于库方违反保留契约提前清除,按契约违例走运维追责通道(契约条款见 Q7/Q9;该消息的死信处置本身不变。
## 10. 开放问题索引 ## 10. 开放问题索引
| 编号 | 待确认事项 | 本文相关章节 | | 编号 | 待确认事项 | 本文相关章节 |
|---|---|---| |---|---|---|
| Q2 | 信箱 ID 单调承诺;最大提交时延;空洞与迟到处理 | §5.1 | | Q2 | 信箱 ID 单调承诺;最大提交时延;空洞与迟到处理 | §5.1、§6 |
| Q6 | 重放 deadline 与人工处置期限的取值(决定 §5.2 的 `R` | §5.2、§9 |
| Q7 | 处理标记值集与写权限;原文保留期;处理时间语义 | §5.2、§6 | | Q7 | 处理标记值集与写权限;原文保留期;处理时间语义 | §5.2、§6 |
| Q8 | 逐类覆盖清单(积压摸底的类型分布依据) | §5.3 |
| Q9(新增) | 清除执行方与 DDL 授权;方案 A / B 选型 | §6 | | Q9(新增) | 清除执行方与 DDL 授权;方案 A / B 选型 | §6 |
| Q10(新增) | 出站消费方、ACK 列语义、出站清理与去重契约 | §7 | | Q10(新增) | 出站消费方、ACK 列语义、出站清理与去重契约 | §7 |
| Q11(新增) | 上游 `SEQN` 重置规则与业务身份的日期边界 | design.md §2.2 | | Q11(新增) | 上游 `SEQN` 重置规则与业务身份的日期边界 | design.md §2.2 |
| Q12(新增) | 历史积压批次“不再处理”的确认主体、审批留痕与跳过值集 | §5.3 |
Q9Q11 的完整登记见 [user-stories.md](user-stories.md) §6 的 Q 表。 Q6Q12 的完整登记见 [user-stories.md](user-stories.md) §6 的 Q 表。
## 11. 不变量 ## 11. 不变量
@@ -206,5 +211,5 @@ Q9Q11 的完整登记见 [user-stories.md](user-stories.md) §6 的 Q 表。
- 处理标记单调:任何路径只将空标写为已处理,不回撤、不覆盖。 - 处理标记单调:任何路径只将空标写为已处理,不回撤、不覆盖。
- 水位不越过未入队的 ID;遇空洞即停。 - 水位不越过未入队的 ID;遇空洞即停。
- 执行清除前,边界内全部行已持有处理标记;物理删除仅发生在归档成功之后(追加写入与分区留档均构成归档成功)。 - 执行清除前,边界内全部行已持有处理标记;物理删除仅发生在归档成功之后(追加写入与分区留档均构成归档成功)。
- 信箱 ID 全局单调、不断链,在任何清除方案下成立 - 信箱 ID 全局单调、不断链:以 Q2 的 ID 单调承诺与 §6 各方案前提成立为条件(方案 B 依赖 `AUTO_INCREMENT` 种子)
- 对外投递按至少一次设计;端到端恰好一次不在交付范围内。 - 对外投递按至少一次设计;端到端恰好一次不在交付范围内。
+9 -8
View File
@@ -4,7 +4,7 @@
本文定义阶段 A 的实施范围与验收口径:**故事定义要交付什么,验收标准定义怎样证明完成,代码落点说明从哪里改起**。保留 US-01US-15、OPS-1OPS-4 编号,便于关联已有任务和测试。 本文定义阶段 A 的实施范围与验收口径:**故事定义要交付什么,验收标准定义怎样证明完成,代码落点说明从哪里改起**。保留 US-01US-15、OPS-1OPS-4 编号,便于关联已有任务和测试。
- 系统边界见 [architecture.md](architecture.md),模块流程见 [design.md](design.md)。本文不重复设计全文,也不以工单状态代替代码验收。 - 系统边界见 [architecture.md](architecture.md),模块流程见 [design.md](design.md)。本文不重复设计全文,也不以工单状态代替代码验收。消息生命周期与信箱清除见 [message-lifecycle.md](message-lifecycle.md),航班规则见 [flight-state.md](flight-state.md)。
- “当前基础”来自本轮代码核对,只表示有接口或部分实现,不表示故事完成。`KEEP` 是保留业务兼容,`FIX` 是明确修正旧缺陷,`DEFERRED` 不进入阶段 A。 - “当前基础”来自本轮代码核对,只表示有接口或部分实现,不表示故事完成。`KEEP` 是保留业务兼容,`FIX` 是明确修正旧缺陷,`DEFERRED` 不进入阶段 A。
- “信箱落信、PG 入队、业务处理完成、信箱回填、下游确认”是五个独立事实,接口、日志和测试必须分开表达。 - “信箱落信、PG 入队、业务处理完成、信箱回填、下游确认”是五个独立事实,接口、日志和测试必须分开表达。
- 所有内部迁移只落自有 PG;共享 MySQL 不建表、不增列、不写历史表。本文用 `DATE_PROCESSED / STATUS` 表示逻辑字段,实际列名以库方契约为准。 - 所有内部迁移只落自有 PG;共享 MySQL 不建表、不增列、不写历史表。本文用 `DATE_PROCESSED / STATUS` 表示逻辑字段,实际列名以库方契约为准。
@@ -36,7 +36,7 @@
**验收标准** **验收标准**
1. 按配置周期、ID 升序、有限批次采集未处理记录;接收层只入队,不解析业务、不回填已处理标记。 1. 按配置周期、ID 升序、有限批次采集信箱行;扫描谓词以 message-lifecycle.md §5.1 为准(按 ID 区间,不以处理标记为谓词)。接收层只入队,不解析业务、不回填已处理标记。
2. 按信箱 ID 幂等建立 PG `PENDING`;重复扫描、并发兼容入队和进程重启都不能重置已有终态。 2. 按信箱 ID 幂等建立 PG `PENDING`;重复扫描、并发兼容入队和进程重启都不能重置已有终态。
3. 快路径用持久水位,补偿路径受控重扫遗漏;本批 PG 入队全部确认后才推进水位。补偿可分页推进,不能被已入队但尚未回填的前一批永久挡住。 3. 快路径用持久水位,补偿路径受控重扫遗漏;本批 PG 入队全部确认后才推进水位。补偿可分页推进,不能被已入队但尚未回填的前一批永久挡住。
4. PG 不可用或批次中途失败时不改信箱标记;恢复后补建遗漏,记录失败次数与扫描进度。 4. PG 不可用或批次中途失败时不改信箱标记;恢复后补建遗漏,记录失败次数与扫描进度。
@@ -44,7 +44,7 @@
**当前基础与落点**`ingress/InboxPoller.kt``InboxEnqueue.kt``infra/persistence/jdbc/JdbcCminmsgInboxRepository.kt` 已有轮询与判重;固定 `afterId=0` 全量扫描,水位与补扫策略未实现(每轮顺带对账回填待办,见 US-09)。扩展 `InboxPollerTest`,补真实 PG/MySQL 中断恢复测试。 **当前基础与落点**`ingress/InboxPoller.kt``InboxEnqueue.kt``infra/persistence/jdbc/JdbcCminmsgInboxRepository.kt` 已有轮询与判重;固定 `afterId=0` 全量扫描,水位与补扫策略未实现(每轮顺带对账回填待办,见 US-09)。扩展 `InboxPollerTest`,补真实 PG/MySQL 中断恢复测试。
**前置**:共享库读契约;Q2 决定严格顺序的端到端验收。 **前置**:共享库读契约;Q2 决定严格顺序的端到端验收。水位与扫描谓词口径以 [message-lifecycle.md](message-lifecycle.md) §5.1 为准。
### US-02 兼容 HTTP 注入报文(KEEP ### US-02 兼容 HTTP 注入报文(KEEP
@@ -192,7 +192,7 @@
**当前基础与落点**:回填意图已在业务事务内预登记到自有 `BACKFILL_TODO`;提交后同步回填(写 `DATE_PROCESSED``PROCESSED`),失败由 `BackfillSweepJob` 到期重试(每 30 秒、指数退避)。剩余缺口:缺 META 或解码失败的死信回填方式,以及“待办落账后再失败 / 提交后崩溃”两个窗口的补偿闭环。 **当前基础与落点**:回填意图已在业务事务内预登记到自有 `BACKFILL_TODO`;提交后同步回填(写 `DATE_PROCESSED``PROCESSED`),失败由 `BackfillSweepJob` 到期重试(每 30 秒、指数退避)。剩余缺口:缺 META 或解码失败的死信回填方式,以及“待办落账后再失败 / 提交后崩溃”两个窗口的补偿闭环。
**前置**:US-03 终态接口;Q7、共享库更新权限。测试覆盖四类终态、事务回滚、重复补偿和重放竞争。 **前置**:US-03 终态接口;Q7、共享库更新权限。覆盖四类终态、事务回滚、重复补偿和重放竞争;生命周期、超期补写与清除口径以 [message-lifecycle.md](message-lifecycle.md) §4/§5.2/§6 为准
### US-10 安全重放与故障处置 ### US-10 安全重放与故障处置
@@ -219,11 +219,11 @@
1. 默认归档接收时间早于 1 天的 SUCCEEDED/SKIPPED/DEAD,保留期可配置 17 天;PENDING/FAILED 禁止归档。明确接收时间字段来源,不混用 UPDATED_AT 或本地入队时间。 1. 默认归档接收时间早于 1 天的 SUCCEEDED/SKIPPED/DEAD,保留期可配置 17 天;PENDING/FAILED 禁止归档。明确接收时间字段来源,不混用 UPDATED_AT 或本地入队时间。
2. 归档到自有 PG `PROC_STATE_HST`;关联 `MSG_EVENT` 的历史目标和保留规则一并设计。仍有未完成投递、回填或恢复依赖时,不移除所需记录。 2. 归档到自有 PG `PROC_STATE_HST`;关联 `MSG_EVENT` 的历史目标和保留规则一并设计。仍有未完成投递、回填或恢复依赖时,不移除所需记录。
3. 迁移与删除在自有库事务内完成,重复执行幂等;失败保留源记录并报告计数。归档后同信箱 ID/业务身份再次到达,仍能按约定去重。 3. 迁移与删除在自有库事务内完成,重复执行幂等;失败保留源记录并报告计数。归档后同信箱 ID/业务身份再次到达,仍能按约定去重。
4. 不写共享 MySQL `CMINMSGS_HST`不清理外部信箱;原文可用性与重放保留期由 Q7/Q8 关联确认。 4. 本系统不写共享 MySQL `CMINMSGS_HST`不清理外部信箱;由库方按 Q9 执行的清除与历史归档见 message-lifecycle.md §6。原文可用性与重放保留期由 Q7/Q8 关联确认。
**当前基础与落点**`PROC_STATE_HST` 未建表,也没有归档处理记录的作业;先确定去重记录保留与关联策略,再补迁移与归档中断测试。航班历史清理(`HistorySweepJob`,属 US-15 红线范围)与本文档处理记录归档不是同一件事,不能混为一谈。 **当前基础与落点**`PROC_STATE_HST` 未建表,也没有归档处理记录的作业;先确定去重记录保留与关联策略,再补迁移与归档中断测试。航班历史清理(`HistorySweepJob`,属 US-15 红线范围)与本文档处理记录归档不是同一件事,不能混为一谈。
**前置**US-03、US-09US-07 提供事件终态规则,US-10 提供恢复保留要求。不依赖 US-15。 **前置**US-03、US-09US-07 提供事件终态规则,US-10 提供恢复保留要求。不依赖 US-15。自有记录归档与信箱保留期的关系以 [message-lifecycle.md](message-lifecycle.md) §8/§9 为准。
### US-12 查询实时航班(KEEP ### US-12 查询实时航班(KEEP
@@ -282,7 +282,7 @@
| 编号 | 必须交付的能力 | 验证证据 | | 编号 | 必须交付的能力 | 验证证据 |
|---|---|---| |---|---|---|
| OPS-1 单写者与启动安全 | 生产缺真实适配器、误用 stub、未启用必需管道时拒启;第二活动写者不能启动,失去写权后不得继续写;中断与停机能正确退出。 | 配置拒启、双实例/失去写权及停机测试。单靠副本数配置不算运行期保护。 | | OPS-1 单写者与启动安全 | 生产缺真实适配器、误用 stub、未启用必需管道时拒启;第二活动写者不能启动,失去写权后不得继续写;中断与停机能正确退出。 | 配置拒启、双实例/失去写权及停机测试。单靠副本数配置不算运行期保护。 |
| OPS-2 可观测与安全 | 真实依赖健康、队列/队头年龄、投递/回填滞后、DEAD 和一致性异常有指标、告警与处理入口;敏感管理操作有访问控制,日志不泄漏口令或完整敏感报文。 | 故障注入触发真实告警,消息到事件可关联;日志出口断开不阻塞业务。 | | OPS-2 可观测与安全 | 真实依赖健康、队列/队头年龄、投递/回填滞后、积压与最老未处理信龄、DEAD 和一致性异常有指标、告警与处理入口;敏感管理操作有访问控制,日志不泄漏口令或完整敏感报文。 | 故障注入触发真实告警,消息到事件可关联;日志出口断开不阻塞业务。 |
| OPS-3 影子隔离 | 自有数据库/schema、topic、服务注册身份隔离;输入只读水位或回放,禁生产回填、真实出站和误注册。 | 配置与集成测试证明生产信箱、状态、topic 未被影子修改。 | | OPS-3 影子隔离 | 自有数据库/schema、topic、服务注册身份隔离;输入只读水位或回放,禁生产回填、真实出站和误注册。 | 配置与集成测试证明生产信箱、状态、topic 未被影子修改。 |
| OPS-4 切流与恢复 | 对拍不少于 7 天,未解释业务字段差异为 0,DLQ 积压为 0MSG_EVENT 最老滞留 < 5 秒;切流后 48 小时观察,24 小时内具备经演练的回滚能力。 | 明确负载与统计口径的对拍报告;Runbook 含停写、排空/水位、状态恢复、写权交接和失败回退,不能只回滚程序版本。 | | OPS-4 切流与恢复 | 对拍不少于 7 天,未解释业务字段差异为 0,DLQ 积压为 0MSG_EVENT 最老滞留 < 5 秒;切流后 48 小时观察,24 小时内具备经演练的回滚能力。 | 明确负载与统计口径的对拍报告;Runbook 含停写、排空/水位、状态恢复、写权交接和失败回退,不能只回滚程序版本。 |
@@ -313,8 +313,9 @@
| Q7 信箱外部契约 | 原目标为成功→SUCCESS、忽略→SKIPPED、重复→DUPLICATE、死信→DEAD;当前 JDBC 写 PROCESSED。新 STATUS 值尚不能假定库方支持。 | 库方认可的状态值、META/缺失字段、权限、原文保留期、出站去重与处理时间语义;若只允许 legacy 集合,显式映射内部原因,不新增外部枚举。 | | Q7 信箱外部契约 | 原目标为成功→SUCCESS、忽略→SKIPPED、重复→DUPLICATE、死信→DEAD;当前 JDBC 写 PROCESSED。新 STATUS 值尚不能假定库方支持。 | 库方认可的状态值、META/缺失字段、权限、原文保留期、出站去重与处理时间语义;若只允许 legacy 集合,显式映射内部原因,不新增外部枚举。 |
| Q8 业务覆盖清单 | “29 FLOP、14 RQRD、21 参考类、2 机位类”只是数量,不能直接当字段规范。 | 将 SIS/XSD、现役 KEEP/FIX 基线整理为逐类矩阵与脱敏样例,列明路由、字段、缺失/清空、通知、数据来源优先级、多桥规则及测试文件。资料不全的类型不标完成。 | | Q8 业务覆盖清单 | “29 FLOP、14 RQRD、21 参考类、2 机位类”只是数量,不能直接当字段规范。 | 将 SIS/XSD、现役 KEEP/FIX 基线整理为逐类矩阵与脱敏样例,列明路由、字段、缺失/清空、通知、数据来源优先级、多桥规则及测试文件。资料不全的类型不标完成。 |
| Q9 信箱清除契约 | 清除由谁执行与 DDL 授权、方案 A/B 选型、现场 MySQL 版本与分区 DDL 能力(message-lifecycle.md §6)。 | 库方书面确认清除授权与方案选型。 | | Q9 信箱清除契约 | 清除由谁执行与 DDL 授权、方案 A/B 选型、现场 MySQL 版本与分区 DDL 能力(message-lifecycle.md §6)。 | 库方书面确认清除授权与方案选型。 |
| Q10 出站信箱契约 | `COUTMSGS` 消费方与顺序、`ACK_DATE_RECV / DATE_SENT / ERROR` 等列语义与写入方、出站清理责任与去重契约(message-lifecycle.md §7legacy 参考见 SIS 规范 COUTMSGS 机制章节)。 | 库方书面确认出站消费、清理与去重契约。 | | Q10 出站信箱契约 | `COUTMSGS` 消费方与顺序、`COUTMSGS_ACK_DATE_RECV / COUTMSGS_ACK_RESEND_TIMES / COUTMSGS_DATE_SENT / COUTMSGS_ERROR` 等列语义与写入方、出站清理责任与去重契约(message-lifecycle.md §7legacy 参考见 SIS 规范 COUTMSGS 机制章节)。 | 库方书面确认出站消费、清理与去重契约。 |
| Q11 上游序号重置 | 上游 `SEQN` 重置规则决定业务身份是否加入日期边界(design.md §2.2,默认关闭)。 | 上游确认重置规则;身份算法变更须另行评审。 | | Q11 上游序号重置 | 上游 `SEQN` 重置规则决定业务身份是否加入日期边界(design.md §2.2,默认关闭)。 | 上游确认重置规则;身份算法变更须另行评审。 |
| Q12 积压跳过授权 | 历史积压批次中“不再处理”的确认主体、审批留痕与跳过值集(message-lifecycle.md §5.3)。 | 业务与库方书面确认该批跳过范围;`PROC_STATE=SKIPPED` 记录原因并保留审计,不允许整段 DELETE。 |
业务日期/日计划采用 `Asia/Shanghai`;持久化与比较使用明确的时间类型和转换规则,不靠服务器默认时区,也不直接比较不同单位的数字。 业务日期/日计划采用 `Asia/Shanghai`;持久化与比较使用明确的时间类型和转换规则,不靠服务器默认时区,也不直接比较不同单位的数字。