docs(acm2-75): 清理空转待决项并对齐全仓旧编号引用
- 删 Q2/Q15/Q19/Q20:时钟偏斜不进判据、实现自定已是结论、原文留存已定、 运营日冲突处置已由 DEAD(PROTOCOL) 定 - Q6 的 abdg 定案本版不提供;Q22 改为 13 类报文到 admin-api 实体表组的映射 (REF_MASTER 单表口径退位);Q23 收窄为 SODT+FLID 幂等重试 - C-1 自清口径四方同步(requirements 非目标、US-03 AC2、architecture §6) - INV-2 吸收回填只写空值;§7 恢复 G-RESP-GUARD - architecture/implementation/README/V1/oracle/Kotlin/seed 中 40+ 处旧编号 按映射重指,check-docs 全绿
This commit is contained in:
+35
-35
@@ -14,10 +14,10 @@
|
||||
|
||||
| 术语 | 语义 |
|
||||
|---|---|
|
||||
| 扫描谓词 | 信箱读取条件「处理时间为空」(`INV-2b`);本系统不以 ID 区间或水位作为消费边界。 |
|
||||
| 扫描谓词 | 信箱读取条件「处理时间为空」(`INV-1`);本系统不以 ID 区间或水位作为消费边界。 |
|
||||
| 队头 | 最小的未完成消息(`PENDING` 与 `FAILED` 都占位)。 |
|
||||
| 终态 | `SUCCEEDED` / `SKIPPED` / `DEAD`;到达后队列方可推进。 |
|
||||
| 回填意图 | 「还欠一次信箱标记」的持久化事实,与终态同一条语句落库,且发生在 Redis 投影写成功之后(`INV-23`)。 |
|
||||
| 回填意图 | 「还欠一次信箱标记」的持久化事实,与终态同一条语句落库,且发生在 Redis 投影写成功之后(`INV-10`)。 |
|
||||
| `R`、`R_keep`、处理标记 | 定义见 [specification.md](specification.md)。 |
|
||||
|
||||
### 1.2 持久化记录
|
||||
@@ -25,7 +25,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` 对 `KAFKA:msg` 是稳定事件身份并决定投递顺序;对 `KAFKA:schd` 是每次接受 upsert 时替换的写代次。`TARGET` 区分 `KAFKA:msg` / `KAFKA:schd`;`PARTITION_KEY` 当前取 `FLID`(`Q4` 定案前为假定,见 `C-29`);`EVENT_TYPE` 区分 UPSERT 与 TOMBSTONE。`KAFKA:schd` 按 `FLID` 单行 upsert,只保留最新 `STATE_VERSION`;`SENT_AT` 在投递确认的同一条 UPDATE 内写入,是保留期判定的唯一基准。 |
|
||||
| `MSG_EVENT` | 等待投递的事件(outbox) | `EVENT_ID` 对 `KAFKA:msg` 是稳定事件身份并决定投递顺序;对 `KAFKA:schd` 是每次接受 upsert 时替换的写代次。`TARGET` 区分 `KAFKA:msg` / `KAFKA:schd`;`PARTITION_KEY` 当前取 `FLID`,`msg` 单分区下不参与路由(`CLM-3`);`EVENT_TYPE` 区分 UPSERT 与 TOMBSTONE。`KAFKA:schd` 按 `FLID` 单行 upsert,只保留最新 `STATE_VERSION`;`SENT_AT` 在投递确认的同一条 UPDATE 内写入,是保留期判定的唯一基准。 |
|
||||
| `REQ_TRACK` | 上游请求及应答关联 | 状态 `PENDING / SENT / DONE / EXPIRED`;保存请求类型、覆盖运营日、发送方、出站信箱 ID 与发送/完成时间;**「同类只允许一个开放请求」的唯一键 = `(请求类型, 覆盖运营日, 发送方)`,且仅对开放状态生效**。 |
|
||||
| `REF_MASTER` | SIS 消息提供的静态参考数据与资源状态(目标表) | `(RTYPE, RKEY)` 唯一;`RTYPE` 类别、合并语义与资源状态见「静态参考数据」;取数路径见 [requirements.md](requirements.md) `US-13`。 |
|
||||
| `FLIGHT_SCHD` | 航班标量及单值异常字段 | `FLID` 主键;运营日与版本、最近消息 ID 用于追踪。变长集合存于资源明细表与 `FLIGHT_ROUTE_POINT`,规则见「航班域」。 |
|
||||
@@ -37,11 +37,11 @@
|
||||
|
||||
`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` 与 `PARAM:msgx.identity.include-day-boundary`);上线后不能随意更换身份算法。
|
||||
业务身份统一由 `Identity.of` 生成:`SNDR | TYPE | STYP | SEQN`。接收时只按信箱 ID 去重,解码后才首次绑定业务身份;重试保留原有绑定,因此自身重试不会被判为重复。身份被另一条记录占用时,当前消息转 `SKIPPED`,记录 `duplicate-of:<id>`。是否加入日期边界取决于上游 `SEQN` 重置周期(见 `C-3`/`Q10` 与 `PARAM:msgx.identity.include-day-boundary`);上线后不能随意更换身份算法。
|
||||
|
||||
**身份绑定是独立的幂等单语句**(`WHERE IDENTITY_KEY IS NULL`),不参与业务事务。它的前提是「报文不可变」(`PRE-7`):同一身份的重发不会被比对内容,若上游改发正文会被判为重复并跳过(`Q15`)。
|
||||
**身份绑定是独立的幂等单语句**(`WHERE IDENTITY_KEY IS NULL`),不参与业务事务。它的前提是「报文不可变」(`Q4`):同一身份的重发不会被比对内容,若上游改发正文会被判为重复并跳过(`Q4`)。
|
||||
|
||||
分派与落库由 `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-3`、`INV-23`);它们不直接触碰 Kafka。领域决策逻辑不执行 I/O。处理步骤的锁跨越 Redis 写,使与航班历史清理的协作覆盖整个步骤(`US-14` AC4)。
|
||||
分派与落库由 `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-3`、`INV-10`);它们不直接触碰 Kafka。领域决策逻辑不执行 I/O。处理步骤的锁跨越 Redis 写,使与航班历史清理的协作覆盖整个步骤(`US-14` AC4)。
|
||||
|
||||
合法但本系统不支持的消息类型:跳过留档、按已处理写回标记(`US-03` AC2),不重试。`REGN` / `RSTA` 是静态参考数据消息,必须分派给 `US-13`,不得跳过。
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
|
||||
### 4.1 收报流程
|
||||
|
||||
`InboxPoller` 按配置周期查信箱中「处理时间为空」的行,按编号升序、每批有上限,在自有 PG 登记 `PENDING`(`INV-2b`)。每轮:
|
||||
`InboxPoller` 按配置周期查信箱中「处理时间为空」的行,按编号升序、每批有上限,在自有 PG 登记 `PENDING`(`INV-1`)。每轮:
|
||||
|
||||
1. 信箱不可读时记日志、等下一轮——这是基础设施失败,不能当成「没有新消息」。
|
||||
2. 取「处理时间为空」的行的升序前 `PARAM:msgx.pipeline.claim-batch` 条。
|
||||
@@ -77,7 +77,7 @@
|
||||
|
||||
### 4.2 顺序依据
|
||||
|
||||
编号即到达顺序的前提见 `PRE-2`/`PRE-3`(`C-30`/`C-3`):ID 按提交顺序分配、空间不复位不复用。较小编号迟提交的最坏结果是被发现得晚(下一轮扫描仍会读到),不会丢。
|
||||
编号即到达顺序的前提已定案(`Q7`):ID 按提交顺序分配、空间不复位不复用。较小编号迟提交的最坏结果是被发现得晚(下一轮扫描仍会读到),不会丢。
|
||||
|
||||
### 4.3 兼容 HTTP 入口
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
|
||||
### 4.4 单实例
|
||||
|
||||
信箱读取不加锁,本设计只在单活动实例下成立(`PRE-5`)。多实例并发扫描会重复登记同一行,主键幂等兜底不会丢消息,但实例级排他仍是前提。
|
||||
信箱读取不加锁,本设计只在单活动实例下成立(`OPS-1`)。多实例并发扫描会重复登记同一行,主键幂等兜底不会丢消息,但实例级排他仍是前提。
|
||||
|
||||
## 5. 主泵调度与单条处理
|
||||
|
||||
@@ -121,7 +121,7 @@ processOne(head):
|
||||
Unsupported → SKIPPED(unsupported)(跳过留档,按已处理写回标记)
|
||||
载荷缺失 → DEAD(MALFORMED)
|
||||
整包协议拒绝 → DEAD(PROTOCOL),不落半包
|
||||
5. 业务型成功,分三步(INV-17b、INV-23):
|
||||
5. 业务型成功,分三步(INV-3、INV-10):
|
||||
① 事务提交:航班变更 + 待发事件
|
||||
② 写 Redis 投影;失败 → 保持未完成,下轮重处理
|
||||
③ 事务提交:SUCCEEDED + 回填意图
|
||||
@@ -137,15 +137,15 @@ processOne(head):
|
||||
|---|---|---|---|---|
|
||||
| 收报入队(`insertIfAbsent`) | 是 | 否 | 否 | 同库事务 |
|
||||
| 身份首次绑定 | 否 | 否 | 否 | 单语句 + 唯一约束 |
|
||||
| 业务型领域变更(航班变更 + 待发事件) | 是 | 是 | 是 | 同库事务(`INV-17b`) |
|
||||
| Redis 投影写 | 否 | 是(处理步骤锁跨越本步) | 否 | 外部副作用,不在 PG 事务内;写成功是终态事务的前置(`INV-23`) |
|
||||
| 业务型终态(`SUCCEEDED` + 回填意图) | 是 | 是 | 否 | 同库事务(`INV-17b`) |
|
||||
| 业务型领域变更(航班变更 + 待发事件) | 是 | 是 | 是 | 同库事务(`INV-3`) |
|
||||
| Redis 投影写 | 否 | 是(处理步骤锁跨越本步) | 否 | 外部副作用,不在 PG 事务内;写成功是终态事务的前置(`INV-10`) |
|
||||
| 业务型终态(`SUCCEEDED` + 回填意图) | 是 | 是 | 否 | 同库事务(`INV-3`) |
|
||||
| 非业务型终态(`MALFORMED` / `PROTOCOL` / `SKIPPED` / `EXHAUSTED`) | 否 | 否 | 否 | 单语句(终态与回填意图同一条 UPDATE) |
|
||||
| 航班历史清理的物理删除 | 是 | 是(落实 `US-14` AC4) | 是 | 同库事务:复查判据 + 历史写入成功后删除 |
|
||||
| 回填(信箱标记 + `BACKFILL_AT`) | 否 | 否 | 否 | 跨库两次单写;幂等可重跑 |
|
||||
| 人工重放(批量改回 `PENDING`) | 否 | 否 | 否 | 单语句批量;`MessageLifecycleGate` 与回填互斥 |
|
||||
|
||||
结论:航班变更与处理终态**不在同一事务**——两者之间夹着 Redis 投影写;同一事务只保证「航班变更 + 事件」与「终态 + 回填意图」各自原子(`INV-3`、`INV-23`)。处理步骤的 `PIPELINE_LOCK` 跨越 Redis 写,使与航班历史清理的协作覆盖整个步骤(`US-14` AC4);该锁的竞争写者是**航班历史清理**,不是别的处理器线程;没有第二写者时该锁不产生额外串行度。
|
||||
结论:航班变更与处理终态**不在同一事务**——两者之间夹着 Redis 投影写;同一事务只保证「航班变更 + 事件」与「终态 + 回填意图」各自原子(`INV-3`、`INV-10`)。处理步骤的 `PIPELINE_LOCK` 跨越 Redis 写,使与航班历史清理的协作覆盖整个步骤(`US-14` AC4);该锁的竞争写者是**航班历史清理**,不是别的处理器线程;没有第二写者时该锁不产生额外串行度。
|
||||
|
||||
### 5.4 历史积压
|
||||
|
||||
@@ -155,7 +155,7 @@ processOne(head):
|
||||
- 不加速、不分流、不走旁路:不允许并行队头,也不允许实时消息跳过积压。
|
||||
- 尝试上限与退避对积压同样生效,不因积压而放宽。
|
||||
- 不再处理的行置 `SKIPPED` 并记录原因,到达终态后走回填通道;不存在「整段 DELETE」的快速通道。
|
||||
- 消化期间的可观测项见 [reference.md](reference.md);完成时限不作对外承诺(`CLM-9`),现场一般为即时处理。
|
||||
- 消化期间的可观测项见 [reference.md](reference.md);完成时限不作对外承诺(`CLM-5`),现场一般为即时处理。
|
||||
|
||||
## 6. 回填
|
||||
|
||||
@@ -174,7 +174,7 @@ ORDER BY BACKFILL_ATTEMPTS ASC, MSG_ID ASC -- 公平轮转,永久失败
|
||||
LIMIT PARAM:msgx.pipeline.backfill-batch
|
||||
```
|
||||
|
||||
超期判据使用**本地入队时间**(`ENQUEUED_AT`),不使用信箱的 `RECEIVED_AT`:后者来自外部时钟,前偏会在「打标即清除」语义下造成提前清除(`PRE-4`)。
|
||||
超期判据使用**本地入队时间**(`ENQUEUED_AT`),不使用信箱的 `RECEIVED_AT`:后者来自外部时钟,前偏会在「打标即清除」语义下造成提前清除。
|
||||
|
||||
### 6.2 四种结果与放弃
|
||||
|
||||
@@ -215,7 +215,7 @@ LIMIT PARAM:msgx.pipeline.backfill-batch
|
||||
|
||||
1. **重复处理判定**:`PROC_STATE` 已存在成功终态 → 幂等成功,仅追加留痕,不重复写入。
|
||||
2. **整包校验**:声明记录数、航班标识与运营日推导等校验失败 → 整包 `DEAD(PROTOCOL)`,不写半包,既有状态保持不变。
|
||||
3. **分批写入**:锁内按 `FLID` 点查归属日,发现同一航班跨运营日即整包回滚并 `DEAD(PROTOCOL)`;通过后分批合并写主表与资源明细,每批一个事务(状态变更 + 待发事件,`INV-17b`)。快照里没有的航班删除:标记已删除、登记删除事件、从 Redis 投影移除(`INV-15b`)。
|
||||
3. **分批写入**:锁内按 `FLID` 点查归属日,发现同一航班跨运营日即整包回滚并 `DEAD(PROTOCOL)`;通过后分批合并写主表与资源明细,每批一个事务(状态变更 + 待发事件,`INV-3`)。快照里没有的航班删除:标记已删除、登记删除事件、从 Redis 投影移除(`INV-7`)。
|
||||
4. **提交结果**:整包完成后在同一事务置消息 `SUCCEEDED` 并预登记回填意图;提交后信箱回填由扫描承接,留痕在事务外追加。处理失败不标记已处理,下轮整包重新处理。
|
||||
|
||||
字段缺失与清空语义、运营日规则见「航班域」。
|
||||
@@ -232,10 +232,10 @@ PENDING → SENT → DONE
|
||||
```
|
||||
|
||||
- 注册同类新请求前使旧开放请求过期;只有 `COUTMSGS` 写入确认后才标记 `SENT` 并关联出站记录;写信箱成功但本地未确认的情况需要补偿与去重,不能无条件重新发送。
|
||||
- 应答优先按已确认的回显字段精确匹配;降级匹配的跨代误配风险必须明确接受并审计(`C-23`)。
|
||||
- 时间比较统一时区与单位,并需定义时钟偏斜容忍;容忍判据未定(`Q5`),在定义前不得把降级匹配描述为精确关联。
|
||||
- 应答按报文类型匹配等待中的开放请求(`US-09` AC2);降级匹配的跨代误配风险必须明确接受并审计。
|
||||
- 时间比较统一时区与单位,判据一律用本地时钟(入队、发送时间),不引入库方或对方时钟。
|
||||
- 参考应答写入自有 `REF_MASTER`,日计划应答走快照流程;请求完成必须在相应数据处理成功之后,超时和迟到应答不能修改已关闭请求对应的状态。
|
||||
- 出站承诺只到落信(`C-4`、`CLM-8`);主 / 共享删除见 `C-5`。
|
||||
- 出站承诺只到落信(`C-4`、`CLM-4`);主 / 共享删除见 `C-5`。
|
||||
|
||||
## 8. 事件投递
|
||||
|
||||
@@ -257,7 +257,7 @@ PENDING → SENT → DONE
|
||||
|
||||
`KAFKA:schd` 行的 `EVENT_ID` 不是跨代次稳定的事件句柄:每次接受更新都从全局序列取得新值并替换原主键,用作条件确认的写代次。重放和人工处置只能针对当前 `(TARGET, PARTITION_KEY, EVENT_ID)`;旧代次被替换后不再能按旧 ID 寻址。升级时若已有重复行,按 `STATE_VERSION DESC, EVENT_ID DESC` 保留一行,使迁移与运行时只进不退规则一致。
|
||||
|
||||
- **只进不退**:仅当新事件的 `STATE_VERSION ≥` 行内现有版本才覆盖,防止迟到的旧事件把新状态压回去。该合并规则以 `C-21`(`FLID` 在保留期内不复用)为前提。
|
||||
- **只进不退**:仅当新事件的 `STATE_VERSION ≥` 行内现有版本才覆盖,防止迟到的旧事件把新状态压回去。该合并规则以 `FLID` 在保留期内不复用(设计前提)为前提。
|
||||
- **条件标记**:发送成功后按**读取时刻的版本**做条件标记(`WHERE STATE_VERSION = <本批版本>`);该行若期间已被更新的版本覆盖,则不标记,留待下一轮重发。
|
||||
|
||||
发送时:
|
||||
@@ -303,7 +303,7 @@ PENDING → SENT → DONE
|
||||
**通则**(对本系统所有持久对象适用)
|
||||
|
||||
- **时间不构成清除依据**:到期只是必要条件,**终局证据才是充分条件**(航班见 `US-14` AC3、`D1`;共享库的清除依据属未确认的清除协议,见 `C-1` 与 `Q9`)。
|
||||
- **证据不随清除消失**:回填失败与放弃的记录在其覆盖的信箱行被清除前保持可查(`C-16`)。
|
||||
- **证据不随清除消失**:回填失败与放弃的记录在其覆盖的信箱行被清除前保持可查(`US-10` AC2)。
|
||||
- **证据缺失或结果不明时按最保守处置**:航班清理为删 0 条(`US-14` AC3、`D1`)。
|
||||
|
||||
**逐对象生命周期**(保留期取值一律见 [reference.md](reference.md))
|
||||
@@ -339,7 +339,7 @@ PENDING → SENT → DONE
|
||||
|
||||
## 10. 容量假设与设计取舍
|
||||
|
||||
本设计按以下量级选型(参数默认值的依据列见 [reference.md](reference.md),可声明性见 `CLM-10`):
|
||||
本设计按以下量级选型(参数默认值的依据列见 [reference.md](reference.md),可声明性见 `CLM-6`):
|
||||
|
||||
- 单机场、单活动实例、单维护者;入站日消息量千级到万级;单条报文量级 ≤ 10⁴ 字节。
|
||||
- 处理延迟秒级可接受;航班可见性延迟不劣于现役(轮询间隔 + 聚合周期秒级)。
|
||||
@@ -351,12 +351,12 @@ PENDING → SENT → DONE
|
||||
|
||||
本章是航班状态的唯一现行设计规范。其他各章只描述管道机制,不重复定义航班域规则。
|
||||
|
||||
系统从共享 MySQL 信箱接收 SIS/AODB 报文,把结果合并到自有 PostgreSQL 中的航班当前态并同步写 Redis 投影,再通过 outbox 投递 Kafka。共享信箱、Redis 投影和 Kafka 都不是状态权威;Redis 投影写在处理完成之前(`INV-23`)。
|
||||
系统从共享 MySQL 信箱接收 SIS/AODB 报文,把结果合并到自有 PostgreSQL 中的航班当前态并同步写 Redis 投影,再通过 outbox 投递 Kafka。共享信箱、Redis 投影和 Kafka 都不是状态权威;Redis 投影写在处理完成之前(`INV-10`)。
|
||||
|
||||
- `FLID` 是航班实例的唯一标识;不得由航班号、日期或资源号推断身份。
|
||||
- `FLIGHT_SCHD` 及其明细表是唯一权威当前态;Redis 投影与展示视图只读,不能作为写入或对账来源(`INV-11b`)。
|
||||
- `FLIGHT_SCHD` 及其明细表是唯一权威当前态;Redis 投影与展示视图只读,不能作为写入或对账来源(`INV-5`)。
|
||||
- 单活动主泵按信箱 FIFO 推进。事务内 `PIPELINE_LOCK` 只串行化本地状态提交,不替代选主或消息认领。
|
||||
- 状态变更与 outbox 事件在同一 PostgreSQL 事务中提交;处理终态与回填意图在同一事务中提交、且晚于 Redis 投影写成功(`INV-17b`);回填与 Kafka 投递在提交后独立重试。
|
||||
- 状态变更与 outbox 事件在同一 PostgreSQL 事务中提交;处理终态与回填意图在同一事务中提交、且晚于 Redis 投影写成功(`INV-3`);回填与 Kafka 投递在提交后独立重试。
|
||||
|
||||
### 11.1 权威模型
|
||||
|
||||
@@ -419,24 +419,24 @@ PENDING → SENT → DONE
|
||||
- 只有 `MAID` 为空的主航班携带 `MAFL`;共享航班只携带自身 `MAID`、`CSOP`、`CSFT`,不携带 `MAFL`,避免下游双向合并。
|
||||
- 同一写代次下投影逐字节稳定,与到达顺序及 `FLNO` 变更无关;重发与消费端比对才有意义。
|
||||
- `MAID = FLID` 的自引用行不进入任何 `MAFL`;`MAID` 指向不存在主航班的悬挂引用不阻断该子航班自身处理,只是不产生投影。
|
||||
- 子航班集合变化的传播见 `INV-22`,事件类型为 `KAFKA:msg` + `KAFKA:schd`;否则整态投影的只进不退写入会丢弃它(见「`schd` 聚合」)。共享航班自身不单独发通知。
|
||||
- 派生主航班投影与产生它的状态写入必须同一事务或一致读快照;按 `MAID` 取子航班要求该列有索引(`INV-17b`、`INV-22`)。
|
||||
- 子航班集合变化的传播见 `US-06` AC2,事件类型为 `KAFKA:msg` + `KAFKA:schd`;否则整态投影的只进不退写入会丢弃它(见「`schd` 聚合」)。共享航班自身不单独发通知。
|
||||
- 派生主航班投影与产生它的状态写入必须同一事务或一致读快照;按 `MAID` 取子航班要求该列有索引(`INV-3`、`US-06` AC2)。
|
||||
|
||||
## 12. 航班域:合并、删除与生命周期
|
||||
|
||||
本章的领域规则只描述「合并成什么态」;决策纯度、事务边界与落库职责见「消息、身份与决策」与 `INV-17b`(`US-03`)。
|
||||
本章的领域规则只描述「合并成什么态」;决策纯度、事务边界与落库职责见「消息、身份与决策」与 `INV-3`(`US-03`)。
|
||||
|
||||
### 12.1 SCHD 日计划
|
||||
|
||||
SCHD DNLD/RESP 在整包校验通过后,分批将报文携带的航班写入当前态,每批一个事务;快照里没有的航班删除:标记已删除、登记删除事件、从 Redis 投影移除(`INV-15b`)。日计划就是主动与 AODB 全量同步一次,以 AODB 下发的数据为准。
|
||||
SCHD DNLD/RESP 在整包校验通过后,分批将报文携带的航班写入当前态,每批一个事务;快照里没有的航班删除:标记已删除、登记删除事件、从 Redis 投影移除(`INV-7`)。日计划就是主动与 AODB 全量同步一次,以 AODB 下发的数据为准。
|
||||
|
||||
日计划里某航班没携带的字段,视为 AODB 已删除该值,本地同步清除(`C-26`)。每个成功写入的航班推进 `STATE_VERSION`,并在同一事务登记 `KAFKA:schd` 与 `KAFKA:msg` 事件。
|
||||
日计划里某航班没携带的字段,视为 AODB 已删除该值,本地同步清除(`C-6`)。每个成功写入的航班推进 `STATE_VERSION`,并在同一事务登记 `KAFKA:schd` 与 `KAFKA:msg` 事件。
|
||||
|
||||
消息重复处理由 `PROC_STATE` 的消息 ID 与 `IDENTITY_KEY` 控制;已成功提交的消息不得再次写入或重复登记事件。整包校验失败时整包不落地(`INV-4`);运营日冲突见 `Q23`。
|
||||
|
||||
### 12.2 动态运行事件(FLOP)
|
||||
|
||||
FLOP 只修改报文表达的字段或集合,其余状态保持不变;目标形态与合并规则见「字段与集合」。`STYP` 必须命中下表白名单,未知值按不支持类型跳过留档(`US-03` AC2),不得进入通用合并。已确认的动态更新在同一事务推进 `STATE_VERSION` 并登记 `KAFKA:msg` 与 `KAFKA:schd`(`INV-17b`);处理终态与回填意图在 Redis 投影写成功后的另一事务中提交(`INV-23`)。同一消息不产生两次效果见 `US-03`;逐类规则未补齐见 `G-FLOP-IDEMPOTENT`。
|
||||
FLOP 只修改报文表达的字段或集合,其余状态保持不变;目标形态与合并规则见「字段与集合」。`STYP` 必须命中下表白名单,未知值按不支持类型跳过留档(`US-03` AC2),不得进入通用合并。已确认的动态更新在同一事务推进 `STATE_VERSION` 并登记 `KAFKA:msg` 与 `KAFKA:schd`(`INV-3`);处理终态与回填意图在 Redis 投影写成功后的另一事务中提交(`INV-10`)。同一消息不产生两次效果见 `US-03`;逐类规则未补齐见 `G-FLOP-IDEMPOTENT`。
|
||||
|
||||
逐类语义以 SIS 的字段表、空标签规则与 Processing Exceptions 为准;下表每一行都必须有一条回归用例钉住「输入与前态 → 目标状态 → 终态与事件」。
|
||||
|
||||
@@ -487,7 +487,7 @@ ADFT 的字段缺失语义尚待上游确认。在确认前采用保守的 Set-o
|
||||
|
||||
主/共享航班级联:删除共享航班时重算主航班 `MAFL`(见「主/共享投影」)并向主航班通知;删除主航班时级联删除其子共享关联并发出删除通知;主/共享关系必须一次原子变更,不出现主已删、子残留的半状态。共享航班增量通常只更新并通知主航班,不直接发共享通知。这些语义同样约束 FDEL 之外的生命周期清理。主/共享关联的增删按 `FLID` 做值比较,不使用引用比较。
|
||||
|
||||
本章的原子级联不回发 EROR(`C-25`、`Q14` 已定案)。
|
||||
本章的原子级联不回发 EROR(`C-5`、`Q12` 已定案)。
|
||||
|
||||
### 12.4 Kafka 与读取
|
||||
|
||||
@@ -536,7 +536,7 @@ ADFT 的字段缺失语义尚待上游确认。在确认前采用保守的 Set-o
|
||||
|
||||
### 13.3 结构与合并语义
|
||||
|
||||
`REF_MASTER` 是对业务暴露的有效参考数据视图,逻辑身份为 `(RTYPE, RKEY)`;普通类别的 `RKEY` 见上表,`RSTA` 的身份必须同时包含 `RTYP` 与 `RSID`。记录保存消息来源、消息批次、刷新时间与按 SIS 标签名组织的字段载荷;重复字段保留输入顺序并表示为有序数组。参考数据保存在独立的数据表中,admin-api 直接读取(`C-31`)。
|
||||
`REF_MASTER` 是对业务暴露的有效参考数据视图,逻辑身份为 `(RTYPE, RKEY)`;普通类别的 `RKEY` 见上表,`RSTA` 的身份必须同时包含 `RTYP` 与 `RSID`。记录保存消息来源、消息批次、刷新时间与按 SIS 标签名组织的字段载荷;重复字段保留输入顺序并表示为有序数组。参考数据保存在独立的数据表中,admin-api 直接读取(`C-10`)。
|
||||
|
||||
- **13 类参考数据**:`DNLD`/`RESP` 是类别全量,整批校验通过后原子发布;`ADD`/`UPD`/`DEL` 是单条全字段增量,按 `(RTYPE, RKEY)` 处理。全量替换只作用于消息指定的同一 `RTYPE`。
|
||||
- **资源状态**:`RSTA-DNLD` 是单条状态更新,按 (`RTYP`, `RSID`) 覆盖;`RSTA-RESP` 是请求返回的多条记录。两者都不以“本包未出现”为理由删除其他资源状态。
|
||||
@@ -560,4 +560,4 @@ SIS 声明的上游忽略与截断口径(`SIS:3.1`/`SIS:3.2`/`SIS:3.4`/`SIS:3.
|
||||
- 数据方向固定为「SIS 消息 → 本网关 → 业务数据库 → admin-api」;本网关不调用 admin-api,不读取其数据库或缓存。
|
||||
- admin-api 只读取已提交的航班状态与 `REF_MASTER` 有效视图,不参与消息解码、合并、批次发布或处理终态判定。
|
||||
- 开发运行时使用自有 PostgreSQL;Oracle 只有通过 `Q1` 要求的方言与集成验证后才可替代,单次部署不得同时把两库作为权威。
|
||||
- admin-api 直接读取本系统写入的静态参考数据表(`C-31`);共享 MySQL 始终只是信箱边界,不承载该读取模型。
|
||||
- admin-api 直接读取本系统写入的静态参考数据表(`C-10`);共享 MySQL 始终只是信箱边界,不承载该读取模型。
|
||||
|
||||
Reference in New Issue
Block a user