docs(acm2-75): 精简重构架构文档并对齐两段事务口径
- architecture.md:§1–§7 全文精简重构——图收敛为拓扑、主流程改七步时序+类别差异表、 约束红线去行话、数据归属去黑话、关键决策按章程瘦身为 D1/D2 - specification.md:INV-17b 补静态参考数据单事务口径 - implementation/reference/README/requirements:对齐扫描谓词与两段事务表述 - AGENTS.md:新增文字纪律与用词归属规则
This commit is contained in:
+16
-11
@@ -2,7 +2,7 @@
|
||||
|
||||
本文件是实现设计的唯一出处,分三章:
|
||||
|
||||
- **处理管道**章:记录模型、状态机、收报与水位、主泵与事务边界、回填、快照与请求、投递、失败恢复与维护作业;
|
||||
- **处理管道**章:记录模型、状态机、收报与扫描谓词、主泵与事务边界、回填、快照与请求、投递、失败恢复与维护作业;
|
||||
- **航班域**章:航班当前态的权威模型、合并与写入语义、删除与重建;
|
||||
- **静态参考数据**章:SIS 消息中的主数据类别与编码、`REF_MASTER` 结构与合并语义、资源状态,以及 admin-api 的下游读取边界。
|
||||
|
||||
@@ -14,11 +14,10 @@
|
||||
|
||||
| 术语 | 语义 |
|
||||
|---|---|
|
||||
| `W`(水位) | 信箱 ID 的连续上界:`(min, W]` 已全部读入自有 PG;只随新 ID 成功入队推进(永久空洞放行是唯一例外)。 |
|
||||
| `holeSince` | `W+1` 处空洞最早被观测到的时刻;无空洞时为 NULL,跨重启保留。 |
|
||||
| 扫描谓词 | 信箱读取条件「处理标记为空」(`INV-2b`);本系统不以 ID 区间或水位作为消费边界。 |
|
||||
| 队头 | 最小的未完成消息(`PENDING` 与 `FAILED` 都占位)。 |
|
||||
| 终态 | `SUCCEEDED` / `SKIPPED` / `DEAD`;到达后队列方可推进。 |
|
||||
| 回填意图 | 「还欠一次信箱标记」的持久化事实,与终态同一条语句落库。 |
|
||||
| 回填意图 | 「还欠一次信箱标记」的持久化事实,与终态同一条语句落库,且发生在 Redis 投影写成功之后(`INV-23`)。 |
|
||||
| `R`、`R_keep`、处理标记 | 定义见 [specification.md](specification.md)。 |
|
||||
|
||||
### 1.2 持久化记录
|
||||
@@ -42,7 +41,7 @@
|
||||
|
||||
**身份绑定是独立的幂等单语句**(`WHERE IDENTITY_KEY IS NULL`),不参与业务事务。它的前提是「报文不可变」(`PRE-7`):同一身份的重发不会被比对内容,若上游改发正文会被判为重复并跳过(`Q15`)。
|
||||
|
||||
分派与落库由 `MessageProcessor` 协调:按 `MsgKind` 把已绑定身份的队头消息交给对应事务协调器(SCHD-DNLD/RESP → `ScheduleProcessor`,ADFT → `AdftProcessor`,FLOP → `FlopProcessor`,FDEL → `FdelProcessor`,`SIS:3.1`~`SIS:3.14` 的静态参考数据消息 → `ReferenceDataProcessor`,其余 → `SKIPPED(unsupported)`)。这些处理器在 `PIPELINE_LOCK` 事务内读取当前完整态,调用纯领域决策逻辑得到下一完整态与待发事件,再统一落库并登记回填意图;它们不直接触碰 Kafka。领域决策逻辑不执行 I/O。
|
||||
分派与落库由 `MessageProcessor` 协调:按 `MsgKind` 把已绑定身份的队头消息交给对应事务协调器(SCHD-DNLD/RESP → `ScheduleProcessor`,ADFT → `AdftProcessor`,FLOP → `FlopProcessor`,FDEL → `FdelProcessor`,`SIS:3.1`~`SIS:3.14` 的静态参考数据消息 → `ReferenceDataProcessor`,其余 → `SKIPPED(unsupported)`)。这些处理器在 `PIPELINE_LOCK` 事务内读取当前完整态,调用纯领域决策逻辑得到下一完整态与待发事件,提交该事务后写 Redis 投影,再在另一事务中登记处理终态与回填意图(`INV-17b`、`INV-23`);它们不直接触碰 Kafka。领域决策逻辑不执行 I/O。处理步骤的锁跨越 Redis 写,因此与航班历史清理的互斥覆盖整个步骤(`INV-18`)。
|
||||
|
||||
合法但本系统不支持的消息类型:跳过留档、按已处理写回标记(`US-03` AC2),不重试。`REGN` / `RSTA` 是静态参考数据消息,必须分派给 `US-13`,不得跳过。
|
||||
|
||||
@@ -122,7 +121,10 @@ processOne(head):
|
||||
Unsupported → SKIPPED(unsupported)(跳过留档,按已处理写回标记)
|
||||
载荷缺失 → DEAD(MALFORMED)
|
||||
整包协议拒绝 → DEAD(PROTOCOL),不落半包
|
||||
5. 业务型成功:处理器在自己的事务内写航班变更 + 待发事件 + SUCCEEDED + 回填意图
|
||||
5. 业务型成功,分三步(INV-17b、INV-23):
|
||||
① 事务提交:航班变更 + 待发事件
|
||||
② 写 Redis 投影;失败 → 保持未完成,下轮重处理
|
||||
③ 事务提交:SUCCEEDED + 回填意图
|
||||
6. 结束:主泵不做回填;回填意图已随终态落库,由扫描补写信箱标记
|
||||
```
|
||||
|
||||
@@ -135,13 +137,15 @@ processOne(head):
|
||||
|---|---|---|---|---|
|
||||
| 收报入队(`insertIfAbsent`) | 是 | 否 | 否 | 同库事务 |
|
||||
| 身份首次绑定 | 否 | 否 | 否 | 单语句 + 唯一约束 |
|
||||
| 业务型终态(处理器产出 `SUCCEEDED`) | 是 | 是 | 是 | 同库事务:航班变更 + 事件 + 终态 + 回填意图 |
|
||||
| 业务型领域变更(航班变更 + 待发事件) | 是 | 是 | 是 | 同库事务(`INV-17b`) |
|
||||
| Redis 投影写 | 否 | 是(处理步骤锁跨越本步) | 否 | 外部副作用,不在 PG 事务内;写成功是终态事务的前置(`INV-23`) |
|
||||
| 业务型终态(`SUCCEEDED` + 回填意图) | 是 | 是 | 否 | 同库事务(`INV-17b`) |
|
||||
| 非业务型终态(`MALFORMED` / `PROTOCOL` / `SKIPPED` / `EXHAUSTED`) | 否 | 否 | 否 | 单语句(终态与回填意图同一条 UPDATE) |
|
||||
| 航班历史清理的物理删除 | 是 | 是(`INV-18`) | 是 | 同库事务:复查判据 + 历史写入成功后删除 |
|
||||
| 回填(信箱标记 + `BACKFILL_AT`) | 否 | 否 | 否 | 跨库两次单写;幂等可重跑 |
|
||||
| 人工重放(批量改回 `PENDING`) | 否 | 否 | 否 | 单语句批量;`MessageLifecycleGate` 与回填互斥 |
|
||||
|
||||
结论:「航班变更与处理终态同事务」只对业务型终态成立。`PIPELINE_LOCK` 的竞争写者是**航班历史清理**(`INV-18`),不是别的处理器线程;没有第二写者时该锁不产生额外串行度。
|
||||
结论:航班变更与处理终态**不在同一事务**——两者之间夹着 Redis 投影写;同一事务只保证「航班变更 + 事件」与「终态 + 回填意图」各自原子(`INV-17b`、`INV-23`)。处理步骤的 `PIPELINE_LOCK` 跨越 Redis 写,使 `INV-18` 的互斥覆盖整个步骤;该锁的竞争写者是**航班历史清理**,不是别的处理器线程;没有第二写者时该锁不产生额外串行度。
|
||||
|
||||
### 5.4 历史积压
|
||||
|
||||
@@ -283,6 +287,7 @@ PENDING → SENT → DONE
|
||||
|---|---|---|
|
||||
| 已落信、未入队 | 信箱行处理标记为空且 PG 无记录 | 重扫补建登记记录 |
|
||||
| 事务执行中 | PG 无该消息终态 | 事务整体回滚,按 `PENDING` 重新处理 |
|
||||
| 领域事务已提交、Redis 写失败或终态未提交 | 该消息无终态(`PENDING`),仍占队头 | 整条消息重处理:投影按当前完整态重写,领域变更依赖逐类幂等(`INV-20b`,`G-FLOP-IDEMPOTENT`),已提交结果不回滚(`INV-16`) |
|
||||
| 事务已提交、标记未写 | 终态行仍持有回填意图 | 仅补写标记;业务处理结果保持不变 |
|
||||
| 标记写入中途 | 标记仍为空 | 重新写入;重复写入同一值无副作用 |
|
||||
| 回填时信箱行已不存在 | 写入 0 行且信箱行不存在 | 立即放弃自动重试(`MISSING_ROW`)并告警;放弃不等于标记已确认,仍需人工对账 |
|
||||
@@ -402,7 +407,7 @@ PENDING → SENT → DONE
|
||||
|
||||
- `ORDINAL` 是持久化顺序,从 1 开始;`SOURCE_SEQ` 是上游序号,允许为空或重复。
|
||||
- 相同资源号不代表同一条分配,禁止按资源号去重。
|
||||
- 每次持久化完整航班状态时,明细表按该 `FLID` 先删后插,以完整合并结果为准(`INV-14`)。
|
||||
- 每次持久化完整航班状态时,明细表按该 `FLID` 先删后插,以完整合并结果为准(`INV-14b`)。
|
||||
- ROUT 与 ERUT 是两类独立集合,不能因相同序号覆盖彼此。
|
||||
- `CHDT` 的类字段固定为 `CCLS`/`CTYP`;当前 wire DTO 与持久化列误写成 `CHCLS`/`CHTYP`,见 `G-FLOP-UNMAPPED`。
|
||||
- 主/共享关系以主表的 `MAID` 为事实来源:`MAID` 是共享航班指向主航班 `FLID` 的引用(非共享航班为 `NULL`);`MAFL` 只在读取和事件投影时从子航班事实派生,不按入站标量解析或保存。
|
||||
@@ -416,7 +421,7 @@ PENDING → SENT → DONE
|
||||
- 同一 `STATE_VERSION` 的投影逐字节稳定(顺序见 `INV-21`),与到达顺序及 `FLNO` 变更无关;重发与消费端比对才有意义。
|
||||
- `MAID = FLID` 的自引用行不进入任何 `MAFL`;`MAID` 指向不存在主航班的悬挂引用不阻断该子航班自身处理,只是不产生投影。
|
||||
- 子航班集合变化的传播见 `INV-22`,事件类型为 `KAFKA:msg` + `KAFKA:schd`;否则整态投影的只进不退写入会丢弃它(见「`schd` 聚合」)。共享航班自身不单独发通知。
|
||||
- 派生主航班投影与产生它的状态写入必须同一事务或一致读快照;按 `MAID` 取子航班要求该列有索引(`INV-17`)。
|
||||
- 派生主航班投影与产生它的状态写入必须同一事务或一致读快照;按 `MAID` 取子航班要求该列有索引(`INV-17b`、`INV-22`)。
|
||||
|
||||
## 12. 航班域:合并、删除与生命周期
|
||||
|
||||
@@ -432,7 +437,7 @@ SCHD DNLD/RESP 在整包校验通过后,分批将报文携带的航班写入
|
||||
|
||||
### 12.2 动态运行事件(FLOP)
|
||||
|
||||
FLOP 只修改报文表达的字段或集合,其余状态保持不变;目标形态与合并规则见「字段与集合」。`STYP` 必须命中下表白名单,未知值按不支持类型跳过留档(`US-03` AC2),不得进入通用合并。已确认的动态更新在同一事务推进 `STATE_VERSION`、登记 `KAFKA:msg` 与 `KAFKA:schd`、提交处理终态与回填意图;同一消息重复处理不得重复产生业务效果(`INV-17b`、`INV-20b`)。
|
||||
FLOP 只修改报文表达的字段或集合,其余状态保持不变;目标形态与合并规则见「字段与集合」。`STYP` 必须命中下表白名单,未知值按不支持类型跳过留档(`US-03` AC2),不得进入通用合并。已确认的动态更新在同一事务推进 `STATE_VERSION` 并登记 `KAFKA:msg` 与 `KAFKA:schd`(`INV-17b`);处理终态与回填意图在 Redis 投影写成功后的另一事务中提交(`INV-23`)。同一消息重复处理不得重复产生业务效果(`INV-20b`)。
|
||||
|
||||
逐类语义以 SIS 的字段表、空标签规则与 Processing Exceptions 为准;下表每一行都必须有一条回归用例钉住「输入与前态 → 目标状态 → 终态与事件」。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user