docs: remove retired schedule generation design
This commit is contained in:
+69
-257
@@ -1,299 +1,111 @@
|
||||
# 航班运行数据接入与当前状态管理设计
|
||||
# 运营航班状态设计
|
||||
|
||||
本模块从共享 MySQL 信箱接收 AODB 报文,在本地库维护航班当前态,再通过 Kafka 发布变化。
|
||||
|
||||
未标注内容即规范要求;开放与待定项汇总在 §10。
|
||||
本文是航班状态的唯一现行设计规范。它定义权威数据、处理语义、生命周期和对外投递;其他文档只描述管道或产品验收,不重复定义航班状态规则。
|
||||
|
||||
## 1. 目标与边界
|
||||
|
||||
1. **当前态唯一**:AODB 是业务事实来源,本地库是本模块唯一查询源。
|
||||
2. **严格有序**:单活动主泵按信箱 FIFO 处理消息。
|
||||
3. **原子提交**:航班状态、处理结果、待发事件在同一事务提交。
|
||||
4. **可恢复**:信箱回填与 Kafka 投递可独立重试,不重算业务。
|
||||
5. **完整保存**:变长资源用明细表,不用固定槽位截断。
|
||||
系统从共享 MySQL 信箱接收 SIS/AODB 报文,把结果合并到自有 PostgreSQL 中的航班当前态,再通过 outbox 投递 Kafka。共享信箱和 Kafka 都不是状态权威,也不参与本地事务的分布式提交。
|
||||
|
||||
边界:只同步报文、维护当前态,不推导取消、延误、备降等业务状态。`PIPELINE_LOCK` 只串行化数据库事务,不能代替消息认领、选主与故障切换。
|
||||
- `FLID` 是航班实例的唯一标识;不得由航班号、日期或资源号推断身份。
|
||||
- `FLIGHT_SCHD` 及其明细表是唯一权威当前态;展示视图只读,不能作为写入或对账来源。
|
||||
- 单活动主泵按信箱 FIFO 推进。事务内 `PIPELINE_LOCK` 只串行化本地状态提交,不替代选主或消息认领。
|
||||
- 状态写入、outbox 事件、处理终态和回填待办在同一 PostgreSQL 事务中提交;回填与 Kafka 投递在提交后独立重试。
|
||||
|
||||
## 2. 数据来源与语义
|
||||
现场目标库为 Oracle 11g;当前已验证的实现基准是 PostgreSQL。Oracle 适配未完成前,不能把它视为可切换的运行时选项。
|
||||
|
||||
| 来源 | 作用 |
|
||||
## 2. 权威模型
|
||||
|
||||
| 对象 | 职责 |
|
||||
|---|---|
|
||||
| SCHD `DNLD`/`RESP` | 按 `FLID` upsert 完整航班基准状态,字段完整替换(§5);不做名单比对或差删 |
|
||||
| SCHD ADFT | 新增或更新单个临时航班(§2.1) |
|
||||
| FLOP | 更新单个航班运行变化,增量合并,不改运营日 |
|
||||
| FDEL | 终止航班实例,标记删除(§6.2) |
|
||||
| 历史任务 | 归档已结束航班并物理清除(§8) |
|
||||
| `FLIGHT_SCHD` | 一行一个 `FLID`,保存标量字段、`STATE`、`STATE_VERSION`、`OPERATION_DAY`、最近消息 ID 和审计时间。 |
|
||||
| 8 张资源明细表 | 登机门、值机柜台、转盘、计划机位、滑槽、延误、靠撤桥、轮挡等变长集合;主键为 `(FLID, ORDINAL)`。 |
|
||||
| `FLIGHT_ROUTE_POINT` | ROUT 与 ERUT 两类路线点,使用 `ROUTE_KIND` 区分;主键应包含该列,避免两类路线的序号冲突。 |
|
||||
| `PROC_STATE` | 信箱消息的处理终态和业务身份幂等记录。 |
|
||||
| `MSG_EVENT` | 事务 outbox,承载整态投影、变更通知和删除 tombstone。 |
|
||||
| `BACKFILL_TODO` | 共享信箱回填的可重试待办。 |
|
||||
| `SCHD_SNAP_LOG` | 日计划处理留痕,只追加、可重建,不参与状态决策。 |
|
||||
|
||||
字段缺失两种含义:
|
||||
### 2.1 航班身份与运营日
|
||||
|
||||
- 完整快照:未出现 = AODB 已无该数据,**清除本地旧值**。
|
||||
- 增量(FLOP):未出现 = 本次没改,**保留本地值**。
|
||||
`FLID` 是主键。`OPERATION_DAY` 从 SCHD 记录的 `SODT` 按配置的机场时区和切日规则推导;它不是消息接收日或落库日。
|
||||
|
||||
### 2.1 ADFT 语义待确认
|
||||
一旦已写入非空 `OPERATION_DAY`,同一 `FLID` 不得改到另一个运营日。遇到冲突,整包日计划按协议错误拒绝,既有状态保持不变。尚未由日计划收录的航班可以为 `NULL`;这不表示该航班没有运行日,只表示当前模型无法为它确定归属日。
|
||||
|
||||
ADFT 的字段缺失语义尚需按 SIS 条款及真实报文确认,**确认前不得直接沿用 FLOP 的增量合并规则**。若 ADFT 含足以确定运营日的 `SODT`,应据此设置 `OPERATION_DAY`,不得默认留 `NULL`。
|
||||
### 2.2 字段与集合
|
||||
|
||||
## 3. 数据模型
|
||||
标量、异常对象前缀字段和 `SRVT`/`VIPF`/`MAFL` 文本字段存于主表。变长资源完整保存到明细表,保留输入顺序和协议源序号:
|
||||
|
||||
### 3.1 航班实例身份
|
||||
- `ORDINAL` 是持久化顺序,从 1 开始;`SOURCE_SEQ` 是上游序号,允许为空或重复。
|
||||
- 相同资源号不代表同一条分配,禁止按资源号去重。
|
||||
- 每次持久化完整航班状态时,明细表按该 `FLID` 先删后插,以完整合并结果为准。
|
||||
- ROUT 与 ERUT 是两类独立集合,不能因相同序号覆盖彼此。
|
||||
|
||||
- **`FLID`**:AODB 分配的实例 ID(`Number(1-12)`,SIS §3.16.2),全部表的唯一关联键。
|
||||
- **`FLNO`**:展示用航班号,可重复,不参与身份判定。
|
||||
- **`OPERATION_DAY`**:所属运营日,一经确定不可变(§3.5、§5.3)。
|
||||
- **`STATE`**:`ACTIVE` / `DELETED`。所有删除先标记;物理清除只发生在历史归档成功之后,归档结果记录在历史存储,不在当前态保留 `ARCHIVED` 状态。
|
||||
## 3. 合并与写入语义
|
||||
|
||||
同一航班号不同运营日 = 不同 `FLID`。
|
||||
处理器保持纯粹:它根据当前完整态和已解码报文得到下一完整态与待发事件,持久化由统一事务入口执行。
|
||||
|
||||
身份属性变更由 AODB 通过 FDEL 后续接 ADFT 表达。**两条消息的 `FLID` 可能相同,也可能不同**,本模块不得预设一定产生新 `FLID`:
|
||||
### 3.1 SCHD 日计划
|
||||
|
||||
- `FLID` 相同:按同一标识下的生命周期重激活处理(FDEL 置 `DELETED`,ADFT 恢复 `ACTIVE`);
|
||||
- `FLID` 不同:按旧实例终止、新实例建立处理。
|
||||
SCHD DNLD/RESP 在整包校验通过后,逐条将报文携带的航班写入当前态。日计划只更新或创建其携带的 `FLID`,**不会因其他航班未出现在本次报文中而删除任何记录**。
|
||||
|
||||
本模块不得合并实例,也不得由航班号或日期推断两个 `FLID` 是同一实例。
|
||||
日计划在重叠字段上可以覆盖当前动态值;未携带的字段按合并规则保留,显式清空才清除。每个成功写入的航班推进 `STATE_VERSION`,并在同一事务登记 `KAFKA_SCHD` 与 `KAFKA_MSG` 事件。
|
||||
|
||||
### 3.2 表职责
|
||||
消息重放由 `PROC_STATE` 的消息 ID 与 `identity_key` 控制;已成功提交的消息不得再次写入或重复登记事件。整包校验失败或运营日冲突时,整包不落地。
|
||||
|
||||
| 表 | 粒度 | 职责 |
|
||||
|---|---|---|
|
||||
| `FLIGHT_SCHD` | 每 `FLID` 一行 | 标量当前态、`OPERATION_DAY`、`STATE`、`STATE_VERSION`、最近消息 ID |
|
||||
| 8 张资源明细表 | 每 `FLID` 多行 | 登机门、值机柜台、行李转盘、计划机位、滑槽、延误、靠撤桥、轮挡 |
|
||||
| `FLIGHT_ROUTE_POINT` | 每 `FLID` 多行 | ROUT/ERUT 路线点,`ROUTE_KIND` 区分 |
|
||||
| `PIPELINE_LOCK` | 单行 | 串行化状态写事务 |
|
||||
| `PROC_STATE` | 每消息一行 | 处理状态与重试结果;兼作快照重放判定(§5.1) |
|
||||
| `MSG_EVENT`(outbox) | 每事件一行 | 状态、变更、删除通知 |
|
||||
| `REQ_TRACK` / `COUTMSGS` | 每请求一行 | 请求状态与出站 |
|
||||
| `BACKFILL_TODO` | 每待补偿一行 | 共享信箱回填任务 |
|
||||
| `SCHD_SNAP_LOG` | 每快照一行 | 只追加留痕,不参与决策(§5.5) |
|
||||
DNLD、RESP 和 ADFT 均已有路由入口。RESP 的请求匹配闭环、出站请求与超时重发仍是待交付项;未注册处理器不能被视为已实现。
|
||||
|
||||
明细表共 9 张、承载 10 类集合(ROUT 与 ERUT 共用路线表);`ORDINAL` 保留输入顺序,`SOURCE_SEQ` 只存上游序号。
|
||||
### 3.2 动态运行事件
|
||||
|
||||
分层:**决策层**(`FLIGHT_SCHD` 与各运行表)承担正确性;**留痕层**(`SCHD_SNAP_LOG`)只追加、可重建;**证据层**(报文归档)冷路径、仅用于重演审计,**尚未交付**。
|
||||
FLOP 事件只修改它表达的字段或资源集合,其余航班状态保持不变。每个动态子类型的语义都必须有明确 Handler 规则和回归测试,不能只因已被路由就推定其业务语义完整。
|
||||
|
||||
### 3.3 完整当前态
|
||||
动态事件保留既有 `OPERATION_DAY`,也不基于接收时间重新推导它。未知或已删除航班的具体处理遵从对应 Handler 的幂等规则。
|
||||
|
||||
主行 + 全部明细 = 完整当前态。写入前在内存生成完整新状态再落库,明细集合按组先删后插。展示视图是投影,不是权威。
|
||||
### 3.3 删除与重建
|
||||
|
||||
### 3.4 代码共享与过站
|
||||
FDEL 是业务删除入口:仅在 `ACTIVE → DELETED` 时推进版本、保留明细并与 tombstone 同事务登记;重复 FDEL 或不存在的航班按幂等成功处理。
|
||||
|
||||
- 主航班与共享航班是独立实例,各有 `FLID`;共享航班用 `CSOP`/`CSFT` 指向主航班,`MAFL` 存共享列表。
|
||||
- `TAOP`/`TAFL`/`TAID` 是过站关联,不是代码共享。
|
||||
- 删除时共享航班 FDEL 先于主航班;按 `FLID` 各自处理,不做级联推断。
|
||||
物理删除仅由独立历史清理在归档成功后执行。日计划报文不是删除依据。若未经 FDEL 而由生命周期清理,清理前需要登记一次 tombstone;已经 FDEL 的记录不重复发出。
|
||||
|
||||
### 3.5 运营日
|
||||
ADFT 的字段缺失语义尚待上游确认。在确认前采用保守的 Set-only 规则:出现字段可更新,缺失字段不清空;不得把它当成日计划或动态全量替换。新建 ADFT 若带可解析的 `SODT`,按同一运营日规则计算 `OPERATION_DAY`;否则保留为 `NULL`。
|
||||
|
||||
`OPERATION_DAY` 是运行保障日期,不是接收日或落库日。
|
||||
## 4. 处理事务与失败规则
|
||||
|
||||
**计算规则**:按机场运营日规则,由计划运行时间字段(`SODT`)与机场时区(Asia/Shanghai)计算;切日边界由业务配置,不得假设等于接收日期或自然日零点。单日请求范围到运营日的映射、多日窗口中每条记录的归日,均按此规则执行。
|
||||
所有状态处理遵循下列顺序:
|
||||
|
||||
快照取覆盖日;FLOP 保留当前值;ADFT 或先于快照的 FLOP 暂为 `NULL`,被快照收录时补齐(ADFT 含 `SODT` 时直接计算,见 §2.1)。
|
||||
1. 主泵只处理 FIFO 队头,解码并绑定业务身份。
|
||||
2. 校验消息结构、声明数量、航班标识和运营日;协议错误标记 `DEAD`,不提交半包。
|
||||
3. 在一个事务中取得 `PIPELINE_LOCK`,读取当前完整态,计算下一状态,写主表和明细表,登记 outbox 和回填待办。
|
||||
4. 同一事务提交处理终态;任一步失败则整体回滚并按错误类别重试或终止。
|
||||
5. 提交后回填共享信箱并异步投递 outbox;后续失败不得把已提交的 `SUCCEEDED` 改回失败。
|
||||
|
||||
延误跨日仍是同一 `FLID`、运营日不变——SIS §3.16 注释 1 明确日计划不含前日延误航班,保留与清理由本模块负责。
|
||||
`identity_key` 由 `发送方|类型|子类型|序号` 构成,用于业务重复检测。`STATE_VERSION` 是单航班的单调版本,供下游判定新旧;它不是日计划版本,也不表示运营日版本。
|
||||
|
||||
## 4. 更新模型
|
||||
## 5. Kafka 与读取
|
||||
|
||||
以 `FLID` 为唯一边界:
|
||||
`KAFKA_SCHD` 是按 `FLID` 的完整状态投影。Dispatcher 可以合并同一 `FLID` 尚未投递的中间版本,只发最新状态;消费端用 `(FLID, STATE_VERSION, UPDATED_AT)` 防止旧投影覆盖新状态。
|
||||
|
||||
```text
|
||||
SCHD → 完整基准(字段替换,upsert;不改变 DELETED 状态)
|
||||
FLOP/ADFT → 增量合并
|
||||
FDEL → 标记删除(DELETED)
|
||||
ADFT → 生命周期重激活(同 FLID)或新实例建立(不同 FLID)
|
||||
历史任务 → 归档后物理清除(内部清理,不发业务删除事件)
|
||||
```
|
||||
`KAFKA_MSG` 只通知变化,不承载权威状态;两个 topic 不承诺顺序。FDEL 和必要的生命周期清理使用 tombstone:键为 `FLID`,删除记录以 null 值投递,通知下游移除旧状态。
|
||||
|
||||
- 每次成功写入推进 `STATE_VERSION`;状态、事件、处理终态同事务提交。
|
||||
- 主链路无集合删除;删除入口只有 FDEL 与历史归档,均先标记后清除。
|
||||
- **普通 SCHD 不承担恢复语义**:`DELETED` 航班被快照收录时保持 `DELETED` 并记录冲突告警(§5.1);恢复入口只有 ADFT(§6.3)。
|
||||
读取完整航班需要读取主表和全部明细。当前逐航班读取有多次查询,尚未保证跨表一致性快照;批量加载与明确的一致性读边界是后续优化项。
|
||||
|
||||
## 5. SCHD 处理
|
||||
## 6. 生命周期与开放项
|
||||
|
||||
设消息 `M`,记录集 `R`。身份前提:同一 `FLID` 属于唯一运营日;`FLID` 不跨日迁移。
|
||||
运营日过去不等于航班结束。历史清理须同时满足配置保留期与终态证据或足够静默期,先成功写入历史存储,后物理删除当前态;历史存储失败时必须删除零行。
|
||||
|
||||
主链路入口为 `applyScheduleRecords`,对单日快照与滚动窗口统一适用;对单日快照不做任何名单层面的处理。
|
||||
以下事项仍需确认或交付:
|
||||
|
||||
### 5.1 applyScheduleRecords(同一事务)
|
||||
- Oracle 11g 的完整方言与集成验证;
|
||||
- RESP 请求—应答匹配和出站请求重发;
|
||||
- ADFT 缺失字段和 `FLID` 重用的上游语义;
|
||||
- 未归属 `OPERATION_DAY` 航班的终止与保留策略;
|
||||
- ROUT/ERUT 联合主键迁移;
|
||||
- 批量一致性读取,以及动态事件仅在事务内计算一次的收敛。
|
||||
|
||||
1. 锁定 `PIPELINE_LOCK`。
|
||||
2. `M` 在 `PROC_STATE` 已有成功终态 → 重放,直接记幂等成功。
|
||||
3. 校验报文完整性(§5.2),任一失败整包不落地。
|
||||
4. 对每条记录按 §3.5 确定其 `OPERATION_DAY`。
|
||||
5. 校验每个 `FLID` 的既有 `OPERATION_DAY`(§5.3)。
|
||||
6. 按完整快照语义 upsert 每个航班(§5.4);**`DELETED` 航班保持 `DELETED`,记录冲突告警 `SCHD_REVIVE_CONFLICT`,不恢复 `ACTIVE`**。
|
||||
7. 逐航班推进 `STATE_VERSION`,登记状态事件与处理终态。
|
||||
## 7. 不变量
|
||||
|
||||
任一步失败整体回滚。
|
||||
|
||||
### 5.2 报文完整性
|
||||
|
||||
五项校验:`RECS` 0–9999 且等于实收 `FLTR` 数;每条记录含合法数字型 `FLID`;快照内不重复;每条记录的运营日可计算且在报文覆盖范围内。
|
||||
|
||||
**记录完整与成员完整必须分开**:
|
||||
|
||||
- **记录完整**:某 `FLID` 的字段是该航班的完整状态 → 允许覆盖字段。48 小时滚动窗口满足此维度。
|
||||
- **成员完整**:报文含某运营日全部 `FLID`。主链路不使用成员完整性;若将来引入名单对账,需另行设计并单独定案。
|
||||
|
||||
### 5.3 航班归属
|
||||
|
||||
| 主行情况 | 处理 |
|
||||
|---|---|
|
||||
| 不存在 | 创建,`OPERATION_DAY` 按记录计算,`STATE = ACTIVE` |
|
||||
| `NULL` | 首次确定 |
|
||||
| 与记录计算值相同 | 按快照更新状态 |
|
||||
| 与记录计算值不同 | 违反身份约束:不改写、整包拒绝 `DEAD(PROTOCOL)`、告警 `SAME_FLID_ACROSS_OPERATION_DAYS` |
|
||||
|
||||
第四行意味着串日、错发或数据污染:不静默保留,不迁移归属,整包拒绝后交人工确认。
|
||||
|
||||
### 5.4 字段语义
|
||||
|
||||
| 输入 | 字段缺失含义 |
|
||||
|---|---|
|
||||
| `DNLD`/`RESP` | AODB 已无该数据 → 清除本地旧值 |
|
||||
| `FLOP` | 本次没改 → 保留本地值 |
|
||||
| `KAFKA_SCHD` | 当前态没有该字段 → 消费者删除旧值 |
|
||||
|
||||
标量出现 Set、缺失 Clear;集合出现 Replace、缺失 Replace 空集。清除只覆盖正式映射的字段。
|
||||
|
||||
### 5.5 时序约束与留痕
|
||||
|
||||
**快照与 FLOP 的覆盖顺序是核心时序问题。** `SEQN` 重启后不可比、不表达业务新旧,因此**不启用陈旧拦截**,只承诺**按信箱接收顺序形成当前态**。“快照比 FLOP 权威”不成立,不得对外承诺。较旧的 SCHD 晚于 FLOP 到达可能把新动态改回旧值——接收序模型的已知代价,靠上游顺序保证或下一次 FLOP 纠正。`SEQN` 仅用于同会话顺序观测(下降记 `SEQN_REGRESSION` 并告警)。
|
||||
|
||||
事务外追加一条 `SCHD_SNAP_LOG`:
|
||||
|
||||
| 字段 | 说明 |
|
||||
|---|---|
|
||||
| `MSG_ID` / `RECV_AT` | 消息 ID、接收时刻(UTC) |
|
||||
| `SCOPE_START` / `SCOPE_END` | 报文覆盖的运营日范围(单日时两者相等) |
|
||||
| `RECS` / `UPSERTED` / `DURATION_MS` | 规模、写入数、耗时 |
|
||||
| `RESULT` | `COMMITTED` / `REPLAY_SKIPPED` / `ROLLED_BACK` |
|
||||
| `FLAGS` | `EMPTY` / `RECS_DROP` / `SEQN_REGRESSION` / `DAY_MISMATCH` / `SCHD_REVIVE_CONFLICT` |
|
||||
| `ARCHIVE_KEY` | 原文归档引用 |
|
||||
|
||||
规则:`RESULT` 与 `FLAGS` 分列(可“成功且告警”);一行 = 一次尝试,重放也记;留痕不参与决策,写失败只记指标;保留 90 天,按 `(SCOPE_END, RECV_AT)` 清理。
|
||||
|
||||
## 6. 动态事件与删除
|
||||
|
||||
### 6.1 FLOP
|
||||
|
||||
读取完整当前态 → 合并变化 → 保留运营日 → `STATE_VERSION` 加一 → 同事务登记 `KAFKA_MSG`、`KAFKA_SCHD` 与处理结果。
|
||||
|
||||
### 6.2 FDEL
|
||||
|
||||
同一事务内:
|
||||
|
||||
1. 按 `FLID` 定位。
|
||||
2. `STATE = ACTIVE`:置 `DELETED`,推进 `STATE_VERSION`,明细保留,发布删除事件。
|
||||
3. `STATE = DELETED`:记幂等成功,**不推进 `STATE_VERSION`,不重复发布删除事件**。
|
||||
4. 不存在:记幂等成功(迟到、重复不报错)。
|
||||
|
||||
**删除一律标记,不物理清除**:`FLID` 复用未确认(§10)、删除与更新事件可能乱序(§7.3),物理清除统一由历史归档执行(§8.2)。共享航班 FDEL 先于主航班,各自处理,不做级联推断。
|
||||
|
||||
### 6.3 ADFT 恢复
|
||||
|
||||
ADFT 到达且 `FLID` 已存在、`STATE = DELETED`:这是同 `FLID` 生命周期重激活(§3.1),恢复 `ACTIVE`,推进 `STATE_VERSION`,登记状态事件。`FLID` 不存在则按新实例建立。
|
||||
|
||||
## 7. 对外处理
|
||||
|
||||
### 7.1 请求
|
||||
|
||||
经 `REQ_TRACK` 登记、`COUTMSGS` 发出;同类请求只留一条有效,新请求置旧为 `EXPIRED`。**只有 `RESP` 完成 RQFD 请求**,按(运营日、发送方、请求类型)匹配最新一条 `PENDING`;`DNLD` 是主动下发,独立处理,除现场确认的扩展规则外不得用于完成请求。协议无请求关联号,匹配规则待验收。
|
||||
|
||||
主链路不依赖逐日请求;当前只收定时下发的 48 小时窗口即为主链路的正常输入。
|
||||
|
||||
### 7.2 回填
|
||||
|
||||
提交后回填共享信箱;回填失败不得把已提交的 `SUCCEEDED` 改回 `FAILED`。
|
||||
|
||||
### 7.3 Kafka
|
||||
|
||||
`KAFKA_SCHD` 发整态:Dispatcher 合并同一 `FLID` 未发事件,按最新 `STATE_VERSION` 输出。`KAFKA_MSG` 只通知变化。两主题间不保证顺序;整态键缺失表示删除旧值。
|
||||
|
||||
判旧:消费端 `(FLID, STATE_VERSION, UPDATED_AT)`。
|
||||
|
||||
删除用 tombstone:载荷至少含 `FLID`、`STATE_VERSION`、`DELETED`;仅在 `ACTIVE → DELETED` 时发布,与删除同事务登记,投递失败持续重试。物理清除(§8.2)是内部清理,**不再发布业务删除事件**;仅对未经 FDEL、由生命周期直接清除的航班,在清除前补发一次删除事件。即使确认 `FLID` 永不复用,`STATE_VERSION` 也不能省——更新与删除事件仍会乱序;`FLID` 复用风险与 GENERATION 方案见 §10。
|
||||
|
||||
### 7.4 身份不变量
|
||||
|
||||
- `FLID` 是主键;一个 `FLID` 最多一个非空 `OPERATION_DAY`,一经确定不可改。
|
||||
- 同 `FLNO` 不同运营日 = 不同 `FLID`。
|
||||
- 身份变更时 FDEL 与 ADFT 的 `FLID` 可能相同也可能不同(§3.1);不得由航班号或日期推断实例;`FLID` 不同时是终止与新建,不是主键变更。
|
||||
|
||||
`OPERATION_DAY` 不可变由应用层在快照入口校验;需数据库层强化可加触发器或 `WHERE operation_day IS NULL OR operation_day = :d`。
|
||||
|
||||
## 8. 生命周期与清理
|
||||
|
||||
运营日过去不等于航班结束,不能按日期删除。
|
||||
|
||||
### 8.1 历史判定
|
||||
|
||||
**单一时间窗不构成删除依据**;须同时满足“超过配置时间窗”且有终态证据或足够长的静默期:
|
||||
|
||||
- 已取消(`CNCL` 非空)超过 48 小时;
|
||||
- 已完成离港/到港终态(`NAAT`/`NEAT`,字段含义与来源系统需在术语表确认,§10)超过 48 小时;
|
||||
- `STATE = DELETED` 超过 48 小时;
|
||||
- 无终态字段时,最后一次有效更新超过兜底期限(默认 7 天)。
|
||||
|
||||
窗口按机场时区(Asia/Shanghai)计算。
|
||||
|
||||
### 8.2 归档与清除(顺序不可颠倒)
|
||||
|
||||
1. `HISTORY_SWEEP` 选出满足 §8.1 的航班(含 `DELETED`)。
|
||||
2. 写入历史存储。
|
||||
3. 历史存储返回成功的 `FLID` 集合,对应行**物理删除**主行与明细;归档结果只记录在历史存储,当前态不保留归档状态。
|
||||
4. 未经 FDEL 的航班在清除前补发一次删除事件(§7.3);其余不发。
|
||||
5. 失败或不明确的保留重试。
|
||||
|
||||
历史存储未接通时必须删 0 条;绝不允许先删当前态再补历史。**物理清除只发生在本步骤**。
|
||||
|
||||
### 8.3 保留期
|
||||
|
||||
| 对象 | 默认保留 | 前置条件 |
|
||||
|---|---|---|
|
||||
| 留痕 `SCHD_SNAP_LOG` | 90 天 | 按 `(SCOPE_END, RECV_AT)` 清理 |
|
||||
| `OPERATION_DAY = NULL` 航班 | 7 天 | 仍未被快照收录;终止规则未定前只增不删 |
|
||||
|
||||
## 9. 失败与读取
|
||||
|
||||
| 错误 | 处理 | 队头行为 |
|
||||
|---|---|---|
|
||||
| 非法报文、数量不符、容量超限 | `DEAD`,不重试 | 立即释放 |
|
||||
| 未支持类型 | `FAILED(UNSUPPORTED)` | 达阈值转 `DEAD` |
|
||||
| 数据库或内部故障 | `FAILED(INFRA)`,退避重试 | 成功或超限前阻塞 |
|
||||
| 快照含归属日不符的 `FLID` | 整包拒绝 `DEAD(PROTOCOL)`,留痕告警 | 立即释放,交人工确认 |
|
||||
| `SEQN` 回退 / `SCHD_REVIVE_CONFLICT` | 只记 `FLAGS` 并告警 | 不阻塞 |
|
||||
| 留痕写失败 | 只记 error 指标 | 不阻塞 |
|
||||
|
||||
读取:完整航班状态须在一致性读事务中读主表与全部明细,且过滤 `STATE = ACTIVE`。当前逐航班读取有 N+1 问题,主表与明细可能不在同一快照——批量加载与一致性读边界待补。
|
||||
|
||||
## 10. 未定事项
|
||||
|
||||
由 ACM2-31 跟踪:快照与动态事件顺序、FLOP 集合语义、删除事件版本、幂等键生命周期、FIFO 参数、一致性读取、快照完整性校验、Oracle 适配。
|
||||
|
||||
| 事项 | 状态 |
|
||||
|---|---|
|
||||
| SCHD 按 `FLID` upsert 且不恢复 `DELETED`;删除一律标记,物理清除由历史归档执行 | 已定案(§4、§5.1、§6.2、§8.2) |
|
||||
| FDEL + ADFT 的 `FLID` 可能相同或不同 | 已定案为处理规则(§3.1、§6.3);上游实际行为待 SIS 条款核对 |
|
||||
| `OPERATION_DAY` 按机场运营日规则由 `SODT` 与机场时区计算,切日边界业务配置 | 已定案(§3.5);边界值待业务确认 |
|
||||
| ADFT 字段缺失语义 | **待确认**(§2.1);确认前不得沿用 FLOP 合并规则 |
|
||||
| `FLID` 是否会被复用 | **待上游书面确认**;确认前保持 `DELETED` 中间态。若不能保证永不复用,需引入生命周期表 `FLIGHT_ID_LIFECYCLE(FLID, GENERATION, LAST_VERSION)`,对外版本升级为 `(FLID, GENERATION, STATE_VERSION)` |
|
||||
| 上游取消是否必然伴随 FDEL | **待上游确认**;确认前不做任何基于名单缺席的删除 |
|
||||
| 旧快照晚于 FLOP 的覆盖风险 | 接收序模型的已知代价;上游顺序保证待确认(ACM2-31#8) |
|
||||
| `NAAT` / `NEAT` 的业务含义与来源系统 | 待术语表确认(§8.1) |
|
||||
| 逐运营日请求完整日计划 | 未完成;主链路不依赖,是否需要待上游 FDEL 可靠性确认后再评估 |
|
||||
|
||||
当前偏差:GTDT 按 Replace 处理但 FLOP 集合语义未确认;动态事件在锁外预览、事务内重算,目标只算一次;回填待办提交后写,崩溃窗口不可恢复,目标事务内预登记。
|
||||
|
||||
### 规则 M:快照与动态事件的应用顺序
|
||||
|
||||
当前实现按信箱接收顺序应用 SCHD 与 FLOP。SCHD 处理时完整替换对应字段,因此接收顺序上后到的 SCHD 会覆盖先到的 FLOP——**这只是当前实现结果,不代表 SCHD 在业务时间上优先**,不得对外承诺快照权威(ACM2-31#8)。
|
||||
|
||||
### 规范依据(SIS)
|
||||
|
||||
| 结论 | 出处 |
|
||||
|---|---|
|
||||
| 以 AODB 最新数据覆盖本地 | §1.6.2 |
|
||||
| `P` 标签为空 = 删除该值;`O` 标签仅在有值时出现 | §1.6.3 |
|
||||
| 日计划是完整快照;未发送字段表示 AODB 已无该数据,应删除 | §3.16 注释 2、4 |
|
||||
| 子系统不消费的字段可忽略 | §3.16 注释 3 |
|
||||
| 日计划不含前日延误航班,保留与清理由子系统负责 | §3.16 注释 1 |
|
||||
| 主动下发为约 48 小时窗口,请求应答按请求范围 | §3.16 Data Range |
|
||||
| 代码共享为独立实例,删除时共享先于主航班 | §1.6.5 |
|
||||
- 本地 PostgreSQL 当前态是唯一权威;信箱、Kafka、Redis 和展示视图不是权威。
|
||||
- 同一时刻只有一个主泵推进 FIFO 状态;状态、事件、终态和回填意图原子提交。
|
||||
- `FLID` 唯一,已确定的 `OPERATION_DAY` 不可改变。
|
||||
- 报文未携带的字段不会被隐式清空;集合按完整合并结果写入。
|
||||
- 缺席于某个日计划不构成删除理由;删除只由 FDEL 或受控历史清理触发。
|
||||
- 外部副作用失败可重试,不回滚已提交的本地业务结果。
|
||||
|
||||
Reference in New Issue
Block a user