docs(acm2-52): 修正跨文档事实冲突 F1–F9 与错引编号
- F1/F6 HTTP 契约:C-28 目标 ResponseDto + 请求体上限暂定 10MB,Q3 指向 C-28 - F2 legacy 与 SIS 的优先级限定;F3 超期判据对齐 ENQUEUED_AT;F4 改引 D1 - F5 参数默认值改引 reference/PARAM;F7 补 4 条契约状态词;F8 定义 MAID/MAFL 并明确排除共享航班;F9 补 INV-20 - N1/N2 错配编号改引;N3 迁移链指针;N4/M5 白名单补 D-x/OPS-x;N6 补 INV-16/17 映射;N7 加粗规则 - M1 回填退避事实与论证;M2 Q6/Q7;M4 Q4 假定标注;M7 去复述 纯文档,不改代码/迁移/配置/legacy。
This commit is contained in:
+4
-4
@@ -22,7 +22,7 @@
|
||||
| [reference.md](reference.md) | 参数注册表、指标与健康、模块入口、错误分类。 |
|
||||
| [flight-state.md](flight-state.md) | 航班域模型与合并语义。 |
|
||||
| [user-stories.md](user-stories.md) | US / OPS 验收目标。 |
|
||||
| [legacy/](legacy/) | 现役行为基线与外部协议事实([SIS 规范](legacy/SIS_AODB_RMS-V0.1.md)、[XSD](legacy/unisysaodbsis.xsd));与现行文档冲突时以 SIS 为准。 |
|
||||
| [legacy/](legacy/) | 现役行为基线与外部协议事实([SIS 规范](legacy/SIS_AODB_RMS-V0.1.md)、[XSD](legacy/unisysaodbsis.xsd))。外部协议事实(报文结构、字段语义、上游行为)以 SIS/XSD 为准;legacy 现役行为只是基线,已知缺陷不作依据;与本系统目标设计的已知差异见 `C-25`/`C-26`,确认状态见 `Q13`/`Q14`。 |
|
||||
|
||||
`message-lifecycle.md` 已并入 design.md,文件仅保留跳转说明。
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|---|---|---|
|
||||
| 水位 `W`、空洞判定与推进条件 | design「收报与水位」 | contracts 写对库方的承诺 `C-1`–`C-3`;reference 写参数 |
|
||||
| 保留期下界 `R_keep`、清除前置条件 | contracts「保留与清除」 | design 只引 `C-x`;执行步骤在上线前另立 |
|
||||
| 处理标记值集与写权限 | contracts `C-5` | design 只写行为约束「只写空标记、不回撤、不覆盖」(`INV-6`) |
|
||||
| 处理标记值集与写权限 | contracts `C-5` | design 只写行为约束「只写空标记、不回撤、不覆盖」(`INV-7`) |
|
||||
| 回填四结果、放弃语义、`R` 的作用 | design「回填」 | invariants 记结论与可声明性 |
|
||||
| 退避 / `claim-batch` / 回填期限等取值 | reference「参数」 | design 只引 `PARAM:x` |
|
||||
| 消费权排他、ID 不复位、报文不可变、时钟、单实例 | invariants「前提」 | 其他文档只引 `PRE-x` |
|
||||
@@ -41,11 +41,11 @@
|
||||
|
||||
## 4. 引用与写作纪律
|
||||
|
||||
1. **引用只用稳定 ID**:`PRE-x`、`INV-x`、`CLM-x`、`C-x`、`PARAM:x`、`[G-x]`、`[Q-x]`、`US-xx`、`ACM2-nn`。**不再用章节号做跨文档引用。**
|
||||
1. **引用只用稳定 ID**:`PRE-x`、`INV-x`、`CLM-x`、`C-x`、`D-x`、`OPS-x`、`PARAM:x`、`[G-x]`、`[Q-x]`、`US-xx`、`ACM2-nn`。**不再用章节号做跨文档引用。**
|
||||
本条取代旧版 README 的「其他文档引用章节号」规则:章节号随增删章节腐烂,指针失效后必然被改写为复述——重构前实测有 30 处「唯一定义处」与 33 处跨文档章节引用。
|
||||
2. 指针之后**不再复述**被指内容。若两处需要同一段话,说明它放错了位置。
|
||||
3. 文档不记进度,只记「主张是否可对外声明」。进度在 Plane。
|
||||
4. 机制段只写「是什么 / 为什么」。验收 → invariants 验证映射;前置条件、红线与库方方案 → contracts / invariants;参数默认值 → reference;操作步骤在上线/切流前另立规程,设计阶段不写。一句话一个主张;加粗每节 ≤ 3 处。
|
||||
4. 机制段只写「是什么 / 为什么」。验收 → invariants 验证映射;前置条件、红线与库方方案 → contracts / invariants;参数默认值 → reference;操作步骤在上线/切流前另立规程,设计阶段不写。一句话一个主张;只强调关键结论,避免整段加粗。
|
||||
5. 数值只有两个家:参数默认值与指标名在 reference.md;契约数值(保留期、值集、下界)在 contracts.md。
|
||||
|
||||
## 5. 维护清单
|
||||
|
||||
@@ -62,7 +62,7 @@ CIIMS / AODB 等上游
|
||||
|
||||
### 收报与处理
|
||||
|
||||
1. `InboxPoller` 默认每秒按 ID 区间扫描水位 `W` 之后的信箱记录(`ID > W`,**不以处理标记为谓词**),在自有 PG 中建立 `PROC_STATE(PENDING)`;水位与入队在同一事务推进(`INV-2`)。重复扫描不能重复入队,中断后由重扫补建。扫描谓词与水位见 design.md「收报与水位」。
|
||||
1. `InboxPoller` 按 `PARAM:msgx.pipeline.poll-interval` 周期按 ID 区间扫描水位 `W` 之后的信箱记录(`ID > W`,**不以处理标记为谓词**),在自有 PG 中建立 `PROC_STATE(PENDING)`;水位与入队在同一事务推进(`INV-2`)。重复扫描不能重复入队,中断后由重扫补建。扫描谓词与水位见 design.md「收报与水位」。
|
||||
2. 主泵只处理最小未完成 `MSG_ID`。解析报文、绑定业务身份并去重后,分派给 SCHD/FLOP/FDEL/ADFT 处理器。
|
||||
3. 在自有 PG 同一事务内(先取 `PIPELINE_LOCK`)保存航班状态变更(`FLIGHT_SCHD` 与明细表)、`MSG_EVENT` 待发事件、处理终态与回填意图。
|
||||
4. 事务提交后,补写共享信箱的处理标记(外部副作用,由回填退避重试与超期强制补写保障)。
|
||||
@@ -78,10 +78,10 @@ CIIMS / AODB 等上游
|
||||
本节只列约束的**归属**;完整定义与验证映射见 [invariants.md](invariants.md),实现与演进不得违反:
|
||||
|
||||
- 消息严格 FIFO:`INV-3`、`INV-4`、`INV-5`(发现完整性依赖 `PRE-2`/`PRE-3`,当前不可对外声明,见 CLM-1/CLM-2)。
|
||||
- 动态状态单写者与写者集合互斥:`INV-17`、`INV-18`。
|
||||
- 动态状态单写者与写者集合互斥:`D2`、`INV-18`。
|
||||
- 身份去重:`INV-9`(身份组成见 design.md「消息、身份与决策」)。
|
||||
- 快照可恢复与运营日不可变:`INV-12`、`INV-13`。
|
||||
- 物理清除只发生在历史归档之后:`INV-15`(红线见 flight-state.md「生命周期与开放项」)。
|
||||
- 航班当前态的物理清除只发生在历史归档之后:`D1`(红线见 flight-state.md「生命周期与开放项」)。
|
||||
|
||||
这些约束优先于吞吐量优化。单写者降低了并发复杂度,代价是队头阻塞和吞吐上限;如需并行化,必须先重新定义顺序与状态归属,不能只调整线程数。
|
||||
|
||||
@@ -104,7 +104,7 @@ CIIMS / AODB 等上游
|
||||
|---|---|---|
|
||||
| D1 | 航班清场只在历史写入成功后进行,未接通时删 0 条;未经 FDEL 的清场须先补发删除事件。ES 历史投影(阶段 B)暂缓。 | 红线已实现于 `HistorySweepJob`;恢复/去重方案未闭合 |
|
||||
| D2 | 动态状态单写者,生产只允许一个活动实例;多实例必须先具备可靠的排他保护。 | 事务行锁已实现;实例级排他未完成 |
|
||||
| D3 | Kafka 生产要求 `acks=all`、`enable.idempotence=true`、`max.in.flight=1`;不允许通过关闭幂等来满足生产接入。 | 约束未强制:默认 in-flight=5,且可用环境变量覆盖 |
|
||||
| D3 | Kafka 生产要求 `acks=all`、`enable.idempotence=true`、`max.in.flight=1`;不允许通过关闭幂等来满足生产接入。 | 约束未强制:默认值与 D3 不一致(见 reference 参数表),且可用环境变量覆盖 |
|
||||
| D4 | 自有库终态记录只归档到 `PROC_STATE_HST`,不侵入共享库的表结构或保留策略。 | 目标表未建,尚无归档作业 |
|
||||
|
||||
## 8. 部署、切换与运维
|
||||
|
||||
+6
-6
@@ -47,15 +47,15 @@
|
||||
|
||||
### A.4 我们向库方的承诺
|
||||
|
||||
- **C-13** 只读约定区间的信箱行(`ID > W`),单活动实例运行,不引入并行消费者。
|
||||
- **C-14** 不建表、不改表结构、不迁移 schema、不写共享历史表;兼容 HTTP 入口按既有契约写入入站信箱。
|
||||
- **C-15** 处理标记只写 `C-5` 认可的值,不回撤、不覆盖已有非空标记。
|
||||
- **C-13** 只读约定区间的信箱行(`ID > W`),单活动实例运行,不引入并行消费者。`[我们单方承诺]`
|
||||
- **C-14** 不建表、不改表结构、不迁移 schema、不写共享历史表;兼容 HTTP 入口按既有契约写入入站信箱。`[我们单方承诺]`
|
||||
- **C-15** 处理标记只写 `C-5` 认可的值,不回撤、不覆盖已有非空标记。`[我们单方承诺]`
|
||||
|
||||
## B. 上游(SIS / AODB)
|
||||
|
||||
- **C-20** 业务身份四元组 `SNDR|TYPE|STYP|SEQN` 的语义由上游定义;`SEQN` 的取值范围与回绕见 SIS §2.8.1。**重置周期未知**,它决定业务身份是否加入日期边界(默认不加)。`SNDR` 取值域也需对拍(SIS 为 AODB/RMS,legacy 实发 OSH5 等)。`[待确认 Q11]`
|
||||
- **C-21** `FLID` 在保留期内不复用。若复用,事件版本(`STATE_VERSION`)必须按 incarnation 作用域,否则「保留最新版本」的合并规则会把新航班的事件压掉,旧 tombstone 也可能删掉在用航班。`[待确认 Q16]`
|
||||
- **C-22** 报文不可变(同 `C-4`)。
|
||||
- **C-22** 报文不可变(同 `C-4`)。`[待确认 Q15]`
|
||||
- **C-23** 请求/应答回显契约:目标优先按已确认的回显字段精确匹配;回显未确认时的降级匹配(同类开放请求且报文 `DTTM ≥ sentAt`)存在跨代误配风险,必须明确接受并审计,不得宣称精确关联。比较前统一时区与时间单位。`[待确认 Q5]`
|
||||
- **C-24** 出站信箱 `COUTMSGS`:消费方与消费顺序、`COUTMSGS_ACK_DATE_RECV` / `COUTMSGS_ACK_RESEND_TIMES` / `COUTMSGS_DATE_SENT` / `COUTMSGS_ERROR` 各列语义与写入责任、出站行清除责任与保留期、落信成功但本地未置 `SENT` 时的重复写入风险及下游去重契约,均未确认。本系统对出站的交付承诺只到**落信**为止。`[待确认 Q10]`
|
||||
- **C-25** 主 / 共享删除顺序与 EROR 回报:SIS 要求删主航班前先删子共享航班,顺序不符时 RMS 应向 AODB 回发 EROR(SIS §1.6.1-1.d,事件定义 SIS §4.8);现行设计为幂等原子级联、不回发 EROR。二选一。`[待确认 Q14]`
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
### B.1 我们向上游的承诺
|
||||
|
||||
- **C-28** 兼容 HTTP 入口的响应只表示**接收结果**(成功时为 `text/plain` 的信箱记录 ID),不表示业务处理成功;请求媒体类型、字符集与失败响应仍需与现役逐项对拍。`[待确认 Q3]`
|
||||
- **C-28** 兼容 HTTP 入口的响应只表示**接收结果**,不表示业务处理成功:目标为现役 `ResponseDto`(`is_success` / `body`),请求体上限暂定 10MB;请求媒体类型、字符集与失败响应仍需与现役逐项对拍。`[待确认 Q3]`
|
||||
- **C-29** 对外投递按**至少一次**设计,不承诺端到端恰好一次;Kafka 消息的 key 为 `FLID`,同一 `FLID` 内保序,跨 `FLID` 不承诺顺序。`[待确认 Q4]`
|
||||
|
||||
## C. 待确认事项台账(Q)
|
||||
@@ -73,7 +73,7 @@
|
||||
|---|---|---|---|---|
|
||||
| Q1 | 权威存储(内部方向) | 自有 PG 单库权威 + 无损明细;现场供库目标 Oracle 11g | — | 已定案(内部),Oracle 适配与部署验收另计 |
|
||||
| Q2 | 信箱 ID 单调、ID 分配→事务可见时延上界、ID 空间不复位;空洞与迟到处置 | 时延按 5 分钟 `max-commit-delay`(**缺少依据的占位值**,不可由 SIS `Expiry` 推导) | 发现完整性声明、空洞老化阈值、补偿扫描窗口、水位不可逆性 | 未确认 |
|
||||
| Q3 | HTTP 契约:媒体类型、字符集、错误码、查询接口对拍 | 成功为 `text/plain` 记录 ID | 兼容入口验收 | 未确认 |
|
||||
| Q3 | HTTP 契约:媒体类型、字符集、错误码、查询接口对拍 | 目标与上限见 `C-28` | 兼容入口验收 | 未确认 |
|
||||
| Q4 | Kafka wire:发送粒度、key、去重标识、分区与批次确认 | 逐 `FLID` 发送,key=`FLID` | 投递契约 | 未确认 |
|
||||
| Q5 | 请求匹配:回显字段可靠性与降级匹配 | `RQFD` 60 秒 / `RQRD` 30 秒超时 | 请求跟踪闭环 | 未确认 |
|
||||
| Q6 | 重放期限与人工处置期限的取值(唯一作用是决定 `R_keep` 下界) | `R` = 30 天;重放/处置期限未定 | `R_keep` 取值 | 未确认 |
|
||||
|
||||
+5
-5
@@ -24,7 +24,7 @@
|
||||
| 记录 | 用途 | 关键约束 |
|
||||
|---|---|---|
|
||||
| `PROC_STATE` | 入站消息的处理状态、身份、尝试次数、错误原因与回填事实 | `MSG_ID = CMINMSGS_ID` 主键防重复入队;`IDENTITY_KEY` 唯一约束防业务重复;按最小未完成 `MSG_ID` 取队头;`BACKFILL_NEXT_AT` 非空 = 还欠一次回填,`BACKFILL_AT` 非空 = 标记已确认,`BACKFILL_ABANDONED_AT/REASON` 非空 = 已停止自动重试(**不等于**标记已确认);`RECEIVED_AT` 复制自信箱接收时间、**可能为 NULL**、仅用于对账与展示;`ENQUEUED_AT` 是本地入队时间、非空、是超期判据的唯一依据。 |
|
||||
| `MSG_EVENT` | 等待投递的事件(outbox) | `EVENT_ID` 决定投递顺序(全局串行分配,见投递);`TARGET` 区分 `KAFKA:msg` / `KAFKA:schd`;`PARTITION_KEY` 恒为 `FLID`;`EVENT_TYPE` 区分 UPSERT 与 TOMBSTONE。`KAFKA:schd` 按 `FLID` 单行 upsert,只保留最新 `STATE_VERSION`。 |
|
||||
| `MSG_EVENT` | 等待投递的事件(outbox) | `EVENT_ID` 决定投递顺序(全局串行分配,见投递);`TARGET` 区分 `KAFKA:msg` / `KAFKA:schd`;`PARTITION_KEY` 当前取 `FLID`(`Q4` 定案前为假定,见 `C-29`);`EVENT_TYPE` 区分 UPSERT 与 TOMBSTONE。`KAFKA:schd` 按 `FLID` 单行 upsert,只保留最新 `STATE_VERSION`。 |
|
||||
| `REQ_TRACK` | 上游请求及应答关联 | 状态 `PENDING / SENT / DONE / EXPIRED`;保存请求类型、覆盖运营日、发送方、出站信箱 ID 与发送/完成时间;**「同类只允许一个开放请求」的唯一键 = `(请求类型, 覆盖运营日, 发送方)`,且仅对开放状态生效**。登记、超时与应答匹配尚未实现 `[G-REQ-TRACK]`。 |
|
||||
| `REF_MASTER` | 静态参考数据(目标表) | `(RTYPE, RKEY)` 唯一;尚未建表,客户端与刷新流程见 user-stories US-13/US-14,US-14 两类映射的存储落点未定。 |
|
||||
| `FLIGHT_SCHD` | 航班标量及单值异常字段 | `FLID` 主键;`OPERATION_DAY` 一经确定不可变;版本与最近消息 ID 用于追踪。变长集合存于 8 张资源明细表与 `FLIGHT_ROUTE_POINT`,规则见 flight-state.md。 |
|
||||
@@ -32,13 +32,13 @@
|
||||
| `SCHD_SNAP_LOG` | 日计划处理留痕 | 只追加、可重建,不参与状态决策;保留期见 reference。 |
|
||||
| `PROC_STATE_HST` | 终态处理记录的归档目标 | 尚未建表 `[G-PROC-HST]`;只归档到自有 PG 的目标表,不落共享库历史表。 |
|
||||
|
||||
字段与索引以 `src/main/resources/db/migration/` 下的 V1 基线为准(Oracle 11g 目录为占位,未接入 Flyway)。报文原文仍从共享信箱读取,原文保留期必须覆盖处理与重放窗口(`C-7`)。
|
||||
字段与索引以 `src/main/resources/db/migration/` 的迁移链为准(Oracle 11g 目录为占位,未接入 Flyway)。报文原文仍从共享信箱读取,原文保留期必须覆盖处理与重放窗口(`C-7`)。
|
||||
|
||||
## 2. 消息、身份与决策
|
||||
|
||||
`XmlCodec`(实装 `JacksonXmlCodec`)把 XML 解码为 `DecodedMessage`,包含 `SNDR / TYPE / STYP / SEQN / DTTM` 元数据、`MsgKind` 与业务载荷。解码失败区分 `MALFORMED`(报文非法,不重试)与可随 codec 修复的 `CODEC_ERROR`。`MsgKind` 是一等分派键:`Schd(RESP/DNLD/ADFT)`、`Flop`、`Fdel`、`Unsupported`。
|
||||
|
||||
业务身份统一由 `Identity.of` 生成:`SNDR | TYPE | STYP | SEQN`。接收时只按信箱 ID 去重,解码后才首次绑定业务身份;重试保留原有绑定,因此自身重试不会被判为重复。身份被另一条记录占用时,当前消息转 `SKIPPED`,记录 `duplicate-of:<id>`。是否加入日期边界取决于上游 `SEQN` 重置周期(见 `C-20`/`Q11`),默认关闭;上线后不能随意更换身份算法。
|
||||
业务身份统一由 `Identity.of` 生成:`SNDR | TYPE | STYP | SEQN`。接收时只按信箱 ID 去重,解码后才首次绑定业务身份;重试保留原有绑定,因此自身重试不会被判为重复。身份被另一条记录占用时,当前消息转 `SKIPPED`,记录 `duplicate-of:<id>`。是否加入日期边界取决于上游 `SEQN` 重置周期(见 `C-20`/`Q11` 与 `PARAM:msgx.identity.include-day-boundary`);上线后不能随意更换身份算法。
|
||||
|
||||
**身份绑定是独立的幂等单语句**(`WHERE IDENTITY_KEY IS NULL`),不参与业务事务。它的前提是「报文不可变」(`PRE-7`):同一身份的重发不会被比对内容,若上游改发正文会被判为重复并跳过(`Q15`)。
|
||||
|
||||
@@ -218,7 +218,7 @@ LIMIT PARAM:msgx.pipeline.backfill-batch
|
||||
1. **取消退避**:已终态但超期未打标的行,每轮扫描都被尝试,不再等退避到期;
|
||||
2. **暂时性故障的放弃期限**:超时、连接失败这类暂时性故障**在 `R` 之前只退避重试、不放弃**;到 `R` 仍未打标才停止自动重试、记入放弃清单并告警。
|
||||
|
||||
放弃判据用**时间**而不是**尝试次数**:按退避表(档位 ≤ 8 秒)与扫描周期,固定次数的实际上限只有几十分钟,一次小时级的共享库故障会把全部待回填行一次性判死,随后必须成批人工恢复——这是必须避免的失败模式。`PARAM:msgx.pipeline.backfill-max-attempts` 因此不再是放弃判据,只保留为单行重试的告警阈值。
|
||||
放弃判据用**时间**而不是**尝试次数**:固定次数不能稳定表达允许的故障持续时间,因此按 `R` 判断放弃,`PARAM:msgx.pipeline.backfill-max-attempts` 只用于告警。
|
||||
|
||||
关于「最终一定打标」,准确表述是三段,缺一不可:
|
||||
|
||||
@@ -322,7 +322,7 @@ PENDING → SENT → DONE
|
||||
|
||||
`JobRunner` 用独立 daemon 线程按周期触发回填扫描、航班历史清理与留痕清理;作业不参与消息 FIFO,也不使到期消息饥饿。`INV-18` 要求历史清理的删除与主泵处理互斥。
|
||||
|
||||
- **航班历史清理**:按保留期与终态/静默判据选候选(含 `DELETED`),先写历史存储,成功后物理删除主行与明细;历史存储未接通或开关关闭时删除 0 条。未经 FDEL、由生命周期直接清除的航班,清除前补发一次删除事件。语义与红线见 flight-state.md。
|
||||
- **航班历史清理**:按 reference 的历史判据选候选(含 `DELETED`),先成功归档再删除;未经 FDEL 的生命周期清除需先补发删除事件。语义与红线见 flight-state.md。
|
||||
- **留痕清理**:`SCHD_SNAP_LOG` 按保留期与 `(SCOPE_END, RECV_AT)` 删除,不依赖历史存储开关。
|
||||
- **处理终态归档**:`PROC_STATE` 终态记录归档至 `PROC_STATE_HST`(尚未建表 `[G-PROC-HST]`)。归档范围只含终态;归档后仍须保留业务去重能力。
|
||||
- **出站事件清理**:见投递清理规则。
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
- 相同资源号不代表同一条分配,禁止按资源号去重。
|
||||
- 每次持久化完整航班状态时,明细表按该 `FLID` 先删后插,以完整合并结果为准。
|
||||
- ROUT 与 ERUT 是两类独立集合,不能因相同序号覆盖彼此。
|
||||
- 主/共享关系由主表字段承载:`MAID` 是共享航班指向主航班 `FLID` 的引用(非共享航班为 `NULL`),`MAFL` 是主航班上的共享航班列表。
|
||||
|
||||
## 3. 合并与写入语义
|
||||
|
||||
@@ -111,4 +112,4 @@ SIS 规定删除主航班时必须先删子共享航班、再删主航班,顺
|
||||
|
||||
## 7. 不变量
|
||||
|
||||
航班域不变量的**定义处是 [invariants.md](invariants.md)**(`INV-11`–`INV-16`),本节不再重复:唯一权威、`FLID` 唯一与 `OPERATION_DAY` 不可变、`STATE_VERSION` 单调、未携带字段不清空、缺席不构成删除、外部副作用失败不回滚已提交结果。与管道共享的部分见同文件的 `INV-17`–`INV-19`。
|
||||
航班域不变量的**定义处是 [invariants.md](invariants.md)**(`INV-11`–`INV-20`),本节不再重复。
|
||||
|
||||
+4
-2
@@ -89,6 +89,8 @@
|
||||
| INV-12 | 运营日冲突 | 整包 `DEAD(PROTOCOL)`,既有状态与版本不变 |
|
||||
| INV-14 / INV-19 | 整包协议拒绝(声明数不符、缺载荷) | 整包不落地、整体回滚、既有状态不变 |
|
||||
| INV-15 | 缺席不删除 | 缺口(F-del 与清理路径分别断言) |
|
||||
| INV-16 | 外部副作用失败后本地结果不变 | 待核对 |
|
||||
| INV-17 | 业务型终态四件套同事务 | 待核对;真实 PG 用例待补(ACM2-39) |
|
||||
| INV-18 | 清理与处理并发 | **缺口**:需断言删除与处理同一 `FLID` 时互斥(关联 ACM2-30) |
|
||||
| INV-20 / CLM-3 | 重放同一条消息 | 缺口:29 类 FLOP 幂等矩阵未补全 |
|
||||
| CLM-4 | 放弃行与清除前提 | 断言放弃行不写标记、不被当作已打标(关联 ACM2-36) |
|
||||
@@ -109,8 +111,8 @@
|
||||
| `G-PROC-HST` | `PROC_STATE_HST` 未建表,终态归档未落地 | US-11;归档能力 |
|
||||
| `G-FLOP-IDEMPOTENT` | 29 类 FLOP 幂等矩阵未补全 | `INV-20`、CLM-3 |
|
||||
| `G-EVENT-RETENTION` | `MSG_EVENT` 已发送行的保留期与清理作业未实现 | outbox 有界性 |
|
||||
| `G-BACKFILL-BACKOFF` | 回填独立退避键(`backfill-backoff-ms` / `-cap-ms`)未实现,暂沿用处理退避表 | 回填重试节奏 |
|
||||
| `G-KAFKA-D3` | `kafka.producers.default.max-in-flight` 默认 5,与架构决策 D3 要求的 1 不一致 | 投递幂等前提 |
|
||||
| `G-BACKFILL-BACKOFF` | 回填独立退避键(`backfill-backoff-ms` / `-cap-ms`)未实现,当前为代码内硬编码(取值见 reference) | 回填重试节奏 |
|
||||
| `G-KAFKA-D3` | `kafka.producers.default.max-in-flight` 与 D3 要求的 1 不一致(取值见 reference) | 投递幂等前提 |
|
||||
| `G-JOB-HEARTBEAT` | 作业心跳、扫描积压、实际回填延迟指标未实现 | CLM-9;回填可观测性 |
|
||||
| `G-REPLAY-CHANNEL` | 「打标即清除」语义下的独立原文保留通道未设计 | CLM-5 |
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
| `msgx.history.idle-hours` | `168` | 假定 | 历史清理的静默期判据 |
|
||||
| `msgx.history.snap-log-retention-days` | `90` | 假定 | `SCHD_SNAP_LOG` 保留天数 |
|
||||
|
||||
| `msgx.proc-state.archive-after` | `1d` | 假定 | **未实现**(`[G-PROC-HST]`);终态记录归档阈值,建议范围 1~7 天;见 `US-11` |
|
||||
### 1.3 信箱与外部依赖(成组登记)
|
||||
|
||||
| 参数组 | 默认 | 依据 | 说明 |
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
**验收标准**
|
||||
|
||||
1. 支持 `text/xml`、`application/xml`、`text/plain`,默认 UTF-8;空报文、超过 10MB 的请求和畸形 XML 返回规范错误,不落信。XML 校验禁用 DTD、外部实体与外部资源访问。
|
||||
1. 支持 `text/xml`、`application/xml`、`text/plain`,默认 UTF-8;空报文、超过请求体上限(见 `C-28`)的请求和畸形 XML 返回规范错误,不落信。XML 校验禁用 DTD、外部实体与外部资源访问。
|
||||
2. 信箱确认落信后返回 ID;PG 入队失败不把已落信伪装成未接收,由 US-01 补建。信箱写入未确认时不返回成功。
|
||||
3. 目标为兼容 `ResponseDto`;固定成功/失败样例、HTTP 状态码、响应媒体类型和错误码表后加入契约测试,见 Q3。成功只承诺信箱落信,不承诺业务处理或下游完成。
|
||||
4. 生产保持内网信任边界,由网关限制来源并审计;外露或跨网络必须先落实认证,不能把免密入口直接暴露。
|
||||
@@ -78,9 +78,9 @@
|
||||
|
||||
1. 只取最小未完成 ID,`PENDING / FAILED` 均占队头;退避未到期不得越过。维护作业由独立线程执行,不参与消息 FIFO;作业必须有界,且不得因争用资源使已到期消息无限饥饿。
|
||||
2. 安全解码 XML,至少覆盖 META、SCHD、FLOP、参考应答与忽略类路由;合法但能力未支持是 `UNSUPPORTED`,不能一律归为非法报文。保留原文以支持诊断和回放。
|
||||
3. 解码后首次绑定 `SNDR|TYPE|STYP|SEQN`;冲突转 `SKIPPED` 并记录原 ID;自身重试保留绑定。生产 `include-day-boundary=false`,更改算法须另行评审上游序号规则。
|
||||
3. 解码后首次绑定 `SNDR|TYPE|STYP|SEQN`;冲突转 `SKIPPED` 并记录原 ID;自身重试保留绑定。生产按 `PARAM:msgx.identity.include-day-boundary` 配置(当前口径不含日期边界);更改算法须先确认 `Q11`。
|
||||
4. `MALFORMED` 直接 `DEAD`;`CODEC_ERROR / UNSUPPORTED / INFRA` 按次数和退避处理,耗尽转 `DEAD(EXHAUSTED)`。不能无限重试未实现类型,也不能立即当非法报文丢弃。
|
||||
5. 终态判据只有尝试上限(默认 5 次),**没有按时间的毒丸**;调度判断注入 `Clock`。积压与人工重放的边界按 Q6 验证。
|
||||
5. 终态判据只有尝试上限(`PARAM:msgx.pipeline.max-attempts`),**没有按时间的毒丸**;调度判断注入 `Clock`。人工重放的可重放范围以 Q6 决定的 `R_keep` 下界为准。
|
||||
6. 主泵在同一 PG 事务提交航班主表/明细、事件与处理结果;终态回填意图通过 US-09 同事务保存。任一步失败整体回滚;提交后只重试外部回填,不重复生成业务事件。
|
||||
7. 领域决策逻辑只读取当前完整态与已解码报文,返回下一完整态和待发事件,不执行 I/O;Processor 作为事务协调器,将状态写入、事件、处理终态与回填意图收敛在同一事务边界内,不直接触碰 Kafka。失败只在持有消息上下文的边界落账,中断向上传递,不作为普通失败吞掉。
|
||||
8. 权威存储不可用或未完成恢复时停止业务处理;不能把“整个状态丢失”误判为“单航班不存在”而批量成功结束增量报文。
|
||||
@@ -149,7 +149,7 @@
|
||||
**验收标准**
|
||||
|
||||
1. `KAFKA:msg` 按目标内 `EVENT_ID` 顺序发送,确认后才标 `SENT`;队头退避时不跳过,发送有超时上限。
|
||||
2. `KAFKA:schd` 只通过 `flushSchd` 聚合,默认 3 秒/500 条;同一 FLID 取批内最新状态,成功确认覆盖对应原事件,失败保持批次可恢复并退避,耗尽可见为 `DEAD`。
|
||||
2. `KAFKA:schd` 只通过 `flushSchd` 聚合,聚合周期与批上限见 reference;同一 FLID 取批内最新状态,成功确认覆盖对应原事件,失败保持批次可恢复并退避,耗尽可见为 `DEAD`。
|
||||
3. 外部接收成功、本地确认失败或进程重启后允许重发;事件标识跨重发稳定,消费者有去重约定,不宣称端到端恰好一次。
|
||||
4. 当前 `KAFKA:msg` 与 `KAFKA:schd` 的分区键均为 `FLID`,schd 逐 `FLID` 发送最新状态,不再是 legacy 的多航班数组。`msg` 是否需按 `SNDR` 分区、发送粒度与去重标识的放置以 Q4 定案为准;定案前不宣称单分区之外的顺序保证。
|
||||
5. 生产强制 `acks=all`、`enable.idempotence=true`、`max.in.flight.requests.per.connection=1`;Broker 支持幂等生产协议并完成实际验证,不允许非幂等降级通过验收。
|
||||
@@ -190,7 +190,7 @@
|
||||
4. 重复补偿效果幂等,保留稳定的完成时间与审计;重放后的新处理结果不能被旧回填任务覆盖。非法报文缺 META 时也有明确回填方式。
|
||||
5. 影子模式禁写,双跑仅一个系统持有标记写权;暴露 PG 终态、回填状态、积压、最老年龄与持续失败告警。
|
||||
|
||||
**当前基础与落点**:回填意图与处理终态同体同行(`PROC_STATE.BACKFILL_*`),随业务事务提交,`BACKFILL_TODO` 已随 V2 迁移下线;终态落库后回填一律由扫描驱动(`BackfillService.sweep` 每 30 秒、指数退避 30 秒起步封顶 15 分钟,处理关键路径不做跨库写),接收时间超过超期期限 `R` 时强制补写(§5.2)。死信同样可补写——回填只需消息 ID,不依赖 META。剩余:Q7 的标记值集与写权限书面确认;影子环境禁写尚未实装。
|
||||
**当前基础与落点**:回填意图与处理终态同体同行(`PROC_STATE.BACKFILL_*`),随业务事务提交,`BACKFILL_TODO` 已随 V2 迁移下线;终态落库后回填一律由定时扫描驱动(`BackfillService.sweep`,扫描周期与退避取值见 [reference.md](reference.md);独立退避键尚未落地 `[G-BACKFILL-BACKOFF]`),处理关键路径不做跨库写;本地入队时间(`ENQUEUED_AT`)超过超期期限 `R` 时强制补写(见 design「回填」)。死信同样可补写——回填只需消息 ID,不依赖 META。剩余:Q7 的标记值集与写权限书面确认;影子环境禁写尚未实装。
|
||||
|
||||
**前置**:US-03 终态接口;Q7、共享库更新权限。覆盖四类终态、事务回滚、重复补偿和重放竞争;生命周期与超期补写以 [design.md](design.md)「中断恢复」「回填」为准,清除口径以 [contracts.md](contracts.md)「保留与清除」为准。
|
||||
|
||||
@@ -216,10 +216,10 @@
|
||||
|
||||
**验收标准**
|
||||
|
||||
1. 默认归档接收时间早于 1 天的 SUCCEEDED/SKIPPED/DEAD,保留期可配置 1~7 天;PENDING/FAILED 禁止归档。明确接收时间字段来源,不混用 UPDATED_AT 或本地入队时间。
|
||||
1. 终态记录在入队后经过的时间(`ENQUEUED_AT`)达到 `PARAM:msgx.proc-state.archive-after` 时列为归档候选;PENDING/FAILED 禁止归档。
|
||||
2. 归档到自有 PG `PROC_STATE_HST`;关联 `MSG_EVENT` 的历史目标和保留规则一并设计。仍有未完成投递、回填或恢复依赖时,不移除所需记录。
|
||||
3. 迁移与删除在自有库事务内完成,重复执行幂等;失败保留源记录并报告计数。归档后同信箱 ID/业务身份再次到达,仍能按约定去重。
|
||||
4. 本系统不写共享 MySQL `CMINMSGS_HST`、不清理外部信箱;由库方按 `Q9` 执行的清除与历史归档见 [contracts.md](contracts.md)「保留与清除」。原文可用性与重放保留期由 Q7/Q8 关联确认。
|
||||
4. 本系统不写共享 MySQL `CMINMSGS_HST`、不清理外部信箱;由库方按 `Q9` 执行的清除与历史归档见 [contracts.md](contracts.md)「保留与清除」。原文可用性与重放保留期由 Q6/Q7 关联确认。
|
||||
|
||||
**当前基础与落点**:`PROC_STATE_HST` 未建表,也没有归档处理记录的作业;先确定去重记录保留与关联策略,再补迁移与归档中断测试。航班历史清理(`HistorySweepJob`,属 US-15 红线范围)与本文档处理记录归档不是同一件事,不能混为一谈。
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
|
||||
**验收标准**
|
||||
|
||||
1. 保留 `GET /all/flights`,直接从自有 PostgreSQL `FLIGHT_SCHD` 查询,过滤 `MAID != NULL` 的共享航班;不改写业务状态。
|
||||
1. 保留 `GET /all/flights`,直接从自有 PostgreSQL `FLIGHT_SCHD` 查询,排除共享航班(`MAID != NULL`,定义见 [flight-state.md](flight-state.md)「字段与集合」);不改写业务状态。
|
||||
2. 固定响应样例、空结果、排序、大小限制及一致性时点。现役未分页时不能无声改为只返回第一页;分页或响应结构变更按 Q3 决定。
|
||||
3. 依赖异常不能伪装为空数组成功;影子只读影子状态,入口有约定的访问控制、限流与审计。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user