From 66d081faaf49bb93a3bde4ea5c39a530c83e30a4 Mon Sep 17 00:00:00 2001 From: windyboy Date: Mon, 13 Apr 2026 16:12:54 +0800 Subject: [PATCH] add aodb detailed planning artifacts and adrs --- .../concepts/aodb/AODB 事件 Schema 草案.md | 252 +++++++++++++++++ .../concepts/aodb/AODB 字段级权威矩阵.md | 65 +++++ .../concepts/aodb/AODB 实施 Backlog.md | 257 ++++++++++++++++++ .../concepts/aodb/AODB 最小部署拓扑草案.md | 176 ++++++++++++ .../concepts/aodb/AODB 高层设计修订计划.md | 79 ++++++ .../aodb/adr/ADR-001 MVP 不引入 Flink.md | 24 ++ .../adr/ADR-002 Kafka 作为唯一事件骨干.md | 24 ++ .../concepts/aodb/adr/ADR-003 事实分层模型.md | 24 ++ .../adr/ADR-004 FlightOperation 写主归属.md | 24 ++ .../aodb/adr/ADR-005 Turnaround 独立建模.md | 24 ++ .../concepts/aodb/adr/ADR-006 资源锁定模型.md | 24 ++ .../aodb/adr/ADR-007 查询与订阅分离.md | 24 ++ .../aodb/adr/ADR-008 Outbox 与 CDC.md | 24 ++ .../aodb/adr/ADR-009 PostgreSQL HA.md | 24 ++ .../aodb/adr/ADR-010 人工裁决事件化.md | 24 ++ 15 files changed, 1069 insertions(+) create mode 100644 airport-wiki/concepts/aodb/AODB 事件 Schema 草案.md create mode 100644 airport-wiki/concepts/aodb/AODB 字段级权威矩阵.md create mode 100644 airport-wiki/concepts/aodb/AODB 实施 Backlog.md create mode 100644 airport-wiki/concepts/aodb/AODB 最小部署拓扑草案.md create mode 100644 airport-wiki/concepts/aodb/AODB 高层设计修订计划.md create mode 100644 airport-wiki/concepts/aodb/adr/ADR-001 MVP 不引入 Flink.md create mode 100644 airport-wiki/concepts/aodb/adr/ADR-002 Kafka 作为唯一事件骨干.md create mode 100644 airport-wiki/concepts/aodb/adr/ADR-003 事实分层模型.md create mode 100644 airport-wiki/concepts/aodb/adr/ADR-004 FlightOperation 写主归属.md create mode 100644 airport-wiki/concepts/aodb/adr/ADR-005 Turnaround 独立建模.md create mode 100644 airport-wiki/concepts/aodb/adr/ADR-006 资源锁定模型.md create mode 100644 airport-wiki/concepts/aodb/adr/ADR-007 查询与订阅分离.md create mode 100644 airport-wiki/concepts/aodb/adr/ADR-008 Outbox 与 CDC.md create mode 100644 airport-wiki/concepts/aodb/adr/ADR-009 PostgreSQL HA.md create mode 100644 airport-wiki/concepts/aodb/adr/ADR-010 人工裁决事件化.md diff --git a/airport-wiki/concepts/aodb/AODB 事件 Schema 草案.md b/airport-wiki/concepts/aodb/AODB 事件 Schema 草案.md new file mode 100644 index 0000000..447aa05 --- /dev/null +++ b/airport-wiki/concepts/aodb/AODB 事件 Schema 草案.md @@ -0,0 +1,252 @@ +# AODB 事件 Schema 草案 + +## 1. 文档定位 + +本文档定义 AODB MVP 阶段的统一事件信封和关键事件 payload 草案,用于实现、联调和消费者契约评审。 + +## 2. 统一事件信封 + +所有事件必须使用统一 envelope: + +```json +{ + "event_id": "uuid", + "event_type": "PublishedFactUpdated", + "schema_version": 1, + "occurred_at": "2026-04-13T16:00:00Z", + "produced_at": "2026-04-13T16:00:01Z", + "source": { + "system": "aodb-flight-service", + "organization": "airport-ops", + "channel": "internal" + }, + "idempotency_key": "string", + "correlation_id": "string", + "aggregate_type": "FlightOperation", + "aggregate_id": "flight_123", + "quality": { + "confidence": "confirmed", + "flags": [] + }, + "payload": {} +} +``` + +## 3. 字段说明 + +| 字段 | 说明 | 必填 | +| --- | --- | --- | +| `event_id` | 全局唯一事件 ID | 是 | +| `event_type` | 事件类型 | 是 | +| `schema_version` | schema 版本 | 是 | +| `occurred_at` | 业务发生时间 | 是 | +| `produced_at` | AODB 产出时间 | 是 | +| `source` | 来源系统和组织 | 是 | +| `idempotency_key` | 幂等键 | 是 | +| `correlation_id` | 关联链路 ID | 是 | +| `aggregate_type` | 聚合类型 | 是 | +| `aggregate_id` | 聚合 ID | 是 | +| `quality` | 可信度和数据质量标记 | 否 | +| `payload` | 事件负载 | 是 | + +## 4. 事件列表 + +### 4.1 `FlightImported` + +用途: + +- 表示计划航班已进入 AODB 标准化流程。 + +```json +{ + "payload": { + "flight_id": "flight_123", + "flight_key": "MU-1234-2026-04-13-1", + "op_date": "2026-04-13", + "carrier": "MU", + "flight_number": "1234", + "leg_no": "1", + "batch_id": "ssim_batch_001" + } +} +``` + +### 4.2 `MilestoneObserved` + +用途: + +- 表示接收到一条原始或标准化里程碑观测。 + +```json +{ + "payload": { + "observation_id": "obs_001", + "flight_id": "flight_123", + "milestone_type": "ALDT", + "observed_value": "2026-04-13T15:22:00Z", + "source_sequence": "aidx-889", + "raw_message_ref": "msg_777" + } +} +``` + +### 4.3 `PublishedFactUpdated` + +用途: + +- 表示 Published Fact 发生变化,是对外共享的关键事件。 + +```json +{ + "payload": { + "flight_id": "flight_123", + "field_name": "ALDT", + "previous_value": "2026-04-13T15:20:00Z", + "current_value": "2026-04-13T15:22:00Z", + "decision_ref": "decision_321", + "published_state_version": 9 + } +} +``` + +### 4.4 `TurnaroundLinked` + +用途: + +- 表示到离港航班形成过站关联。 + +```json +{ + "payload": { + "turnaround_id": "ta_001", + "arrival_flight_id": "flight_arr_001", + "departure_flight_id": "flight_dep_001", + "tail_number": "B-1234", + "link_confidence": "estimated" + } +} +``` + +### 4.5 `ResourceAssigned` + +用途: + +- 表示资源分配已生效。 + +```json +{ + "payload": { + "allocation_id": "alloc_001", + "resource_id": "stand_12", + "resource_type": "Stand", + "flight_id": "flight_123", + "turnaround_id": "ta_001", + "lock_type": "hard", + "assignment_source": "manual", + "validity_window": { + "start_at": "2026-04-13T15:00:00Z", + "end_at": "2026-04-13T16:30:00Z" + } + } +} +``` + +### 4.6 `ResourceConflictDetected` + +用途: + +- 表示资源冲突被识别出来。 + +```json +{ + "payload": { + "resource_id": "stand_12", + "resource_type": "Stand", + "conflict_type": "time_overlap", + "affected_allocations": ["alloc_001", "alloc_002"], + "affected_flights": ["flight_123", "flight_456"], + "rule_ref": "resource.time-window.v1" + } +} +``` + +### 4.7 `AlertRaised` + +用途: + +- 表示告警进入打开状态。 + +```json +{ + "payload": { + "alert_id": "alert_001", + "alert_type": "resource_conflict", + "severity": "high", + "related_aggregate_type": "ResourceAllocation", + "related_aggregate_id": "alloc_001", + "summary": "Stand 12 conflict detected" + } +} +``` + +### 4.8 `ManualDecisionRecorded` + +用途: + +- 表示人工裁决已经完成。 + +```json +{ + "payload": { + "decision_id": "decision_321", + "decision_type": "field_override", + "target_aggregate_type": "FlightOperation", + "target_aggregate_id": "flight_123", + "field_name": "ALDT", + "selected_value": "2026-04-13T15:22:00Z", + "reason": "tower confirmation", + "operator": "ops_user_007" + } +} +``` + +### 4.9 `ReviewTaskOpened` + +用途: + +- 表示复核任务已创建。 + +```json +{ + "payload": { + "review_task_id": "review_001", + "review_type": "milestone_conflict", + "target_aggregate_type": "FlightOperation", + "target_aggregate_id": "flight_123", + "reason": "conflicting ALDT observations" + } +} +``` + +## 5. 版本演进规则 + +- `schema_version` 必须随破坏性变更升级。 +- 非破坏性新增字段只允许追加,不允许重定义现有字段含义。 +- 下游必须按“忽略未知字段”实现兼容。 +- 被废弃字段必须至少保留一个发布周期。 + +## 6. Topic 建议 + +| Topic | 用途 | 分区键 | +| --- | --- | --- | +| `aodb.flight.events` | FlightOperation 和 Published Fact 事件 | `flight_id` | +| `aodb.resource.events` | 资源分配和冲突事件 | `flight_id` | +| `aodb.alert.events` | 告警和处置事件 | `alert_id` | +| `aodb.review.events` | 人工复核和裁决事件 | `target_aggregate_id` | + +## 7. 消费者要求 + +- 必须按 `event_id` 去重。 +- 必须处理至少一次投递。 +- 必须把 `quality.flags` 作为强语义,而不是展示附注。 +- 不得把查询接口结果当作事件流补偿来源。 diff --git a/airport-wiki/concepts/aodb/AODB 字段级权威矩阵.md b/airport-wiki/concepts/aodb/AODB 字段级权威矩阵.md new file mode 100644 index 0000000..d7b4ad6 --- /dev/null +++ b/airport-wiki/concepts/aodb/AODB 字段级权威矩阵.md @@ -0,0 +1,65 @@ +# AODB 字段级权威矩阵 + +## 1. 文档定位 + +本文档用于定义 AODB 关键字段的来源优先级、更正规则、人工覆盖规则和对外可见性。它是 Published Fact 生成和测试用例设计的直接依据。 + +## 2. 适用原则 + +- 规则粒度以字段为准,而不是以“整条航班记录”统一处理。 +- 原始 Observation 永不改写。 +- Published Fact 只能由字段级权威矩阵和裁决逻辑生成。 +- 人工覆盖必须事件化和审计化。 + +## 3. 字段矩阵 + +| 字段 | 字段类别 | 主来源 | 次来源 | 默认可信度规则 | 过期规则 | 更正规则 | 人工覆盖规则 | 对外可见性 | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | +| SIBT / SOBT | 计划时间 | SSIM / 计划导入 | 人工计划调整 | 计划导入为 `reported`,人工调整为 `confirmed` | 新计划版本到达后旧计划失效 | 新批次或更高版本覆盖旧计划 | 允许,必须记录变更原因 | 返回当前值 + 来源 | +| EOBT | 预计时间 | 航司计划源 | 机场运行 | 航司上报优先 | 超过配置阈值后降为 `suspect` | 新版本或更正报文优先 | 允许 | 返回当前值 + 来源 + 可信度 | +| TOBT | 协同计划时间 | 航司 / 地服 | 机场运行 | 航司 / 地服 `confirmed` 高于机场运行 `reported` | 若长时间未更新且实际进度明显偏离,则标记 `suspect` | 显式更正优先 | 允许,必须给出裁决摘要 | 返回当前值 + 裁决摘要 | +| TSAT | 系统计算时间 | AODB / PDS | 机场运行人工调整 | 系统计算缺省 `estimated` | 新一轮计算生成后旧值过期 | 高版本计算结果覆盖低版本 | 允许,需记录算法版本和人工原因 | 返回当前值 + 算法版本 | +| TTOT | 系统计算时间 | AODB / PDS | 机场运行人工调整 | 同 TSAT | 同 TSAT | 同 TSAT | 同 TSAT | 返回当前值 + 算法版本 | +| ELDT | 预计到达时间 | ANSP / 外部运行态 | 系统预测 | ANSP 上报高于系统预测 | 若距当前时间过远且无更新,可信度下降 | 新版本或更正优先 | 允许 | 返回当前值 + 可信度 | +| ALDT | 实际到达时间 | ANSP / 机场运行 | 航司 | ANSP / 机场运行 `confirmed` 优先 | 实际时间不过期,但可被更正 | 明确更正或更高序列覆盖 | 允许,需进入人工裁决 | 返回当前值 + 来源 | +| AIBT | 实际到位时间 | 地服 / 机场运行 | 航司 | 地服 / 机场运行优先 | 实际时间不过期,但可被更正 | 更正优先 | 允许,需人工裁决 | 返回当前值 + 来源 | +| EIBT | 预计到位时间 | 系统计算 | 运行动态派生 | 系统计算缺省 `estimated` | 新估算生成后旧值过期 | 新估算覆盖旧估算并留历史 | 允许 | 返回当前值 + 可信度 | +| AOBT | 实际推出时间 | 地服 / 机场运行 | 航司 | 地服优先 | 实际时间不过期,但可更正 | 更正优先 | 允许,需人工裁决 | 返回当前值 + 来源 | +| ATOT | 实际起飞时间 | ANSP | 航司 / 机场运行 | ANSP 优先 | 实际时间不过期,但可更正 | 更正优先 | 允许,需人工裁决 | 返回当前值 + 来源 | +| Flight Status | 航班状态摘要 | Published Fact 推导 | 人工裁决 | 由里程碑和取消状态综合推导 | 状态持续有效直到新事实生成 | 更正走 Published Fact 重新计算 | 允许,需生成裁决事件 | 返回当前值 + 裁决摘要 | +| Cancelled Flag | 取消标记 | 航司 / 计划源 | 机场运行 | 航司取消优先 | 取消后持续有效,直到明确恢复 | 恢复必须有显式更正 | 允许,需高级别审计 | 返回当前值 + 来源 | +| Turnaround Link | 航班配对 | 系统配对 | 人工配对修正 | 人工修正高于自动配对 | 当关联航班变化时旧配对失效 | 更正产生 `TurnaroundCorrected` | 允许 | 返回当前值 + link_confidence | +| Stand Assignment | 资源分配 | 机场运行系统 | 人工调度 | 自动分配默认为 `estimated`,人工为 `confirmed` | 时间窗失效后不再生效 | 新分配替换旧分配并保留历史 | 必须支持 | 返回当前值 + 覆盖摘要 | +| Gate Assignment | 资源分配 | 机场运行系统 | 人工调度 | 同上 | 同上 | 同上 | 必须支持 | 返回当前值 + 覆盖摘要 | +| Belt Assignment | 资源分配 | 机场运行系统 | 人工调度 | 同上 | 同上 | 同上 | 必须支持 | 返回当前值 + 覆盖摘要 | +| Counter Assignment | 资源分配 | 机场运行系统 | 人工调度 | 同上 | 同上 | 同上 | 必须支持 | 返回当前值 + 覆盖摘要 | + +## 4. 冲突裁决优先级 + +当多个 Observation 竞争同一字段时,按以下顺序裁决: + +1. 字段权威来源优先级 +2. 明确更正 / 更高版本号 +3. `confidence` +4. `occurred_at` +5. `source_sequence` 或 `ingest_sequence` +6. 人工裁决 + +## 5. 最小输出契约 + +对外查询至少返回: + +- `current_value` +- `source` +- `confidence` +- `last_decision_summary`(可空) +- `updated_at` +- `data_quality_flags` + +## 6. 测试场景 + +1. ALDT 出现 ANSP 与航司冲突,系统自动按来源优先级裁决。 +2. TOBT 出现多个地服更正,系统按更正版本和时间序列更新。 +3. Stand Assignment 在延误后重新分配,旧分配转历史,新分配变当前值。 +4. Turnaround 自动配对后被人工修正,系统产生 `TurnaroundCorrected`。 +5. Cancelled Flag 被恢复时,必须有显式更正,不允许静默取消取消状态。 diff --git a/airport-wiki/concepts/aodb/AODB 实施 Backlog.md b/airport-wiki/concepts/aodb/AODB 实施 Backlog.md new file mode 100644 index 0000000..f892984 --- /dev/null +++ b/airport-wiki/concepts/aodb/AODB 实施 Backlog.md @@ -0,0 +1,257 @@ +# AODB 实施 Backlog + +## 1. 文档定位 + +本文档将 AODB 高层设计拆解为可执行实施 backlog,用于排期、分工、估算和测试准备。 + +- 上位输入: + - `AODB 核心需求提炼.md` + - `开源机场运营数据库(AODB)高层设计文档.md` + - `开源技术栈选型决策.md` +- 输出对象: + - Epic / Story / Task + - 验收条件 + - 测试关注点 + +## 2. 里程碑视图 + +| 里程碑 | 目标 | 完成标准 | +| --- | --- | --- | +| M1 | 建立核心文档和 ADR 基线 | 需求、架构、技术栈、ADR 对齐 | +| M2 | 完成核心数据接入和当前态闭环 | SSIM / AIDX / AFTN 接入后能形成 Published Fact | +| M3 | 完成资源分配、冲突和告警闭环 | Stand / Gate / Belt / Counter 的分配和冲突可追溯 | +| M4 | 完成查询、订阅、审计和人工复核闭环 | 外部读取、事件回放、人工裁决可运行 | +| M5 | 完成容灾、压测和上线门禁 | SLO、演练、对账、补偿全部达标 | + +## 3. Epic 清单 + +### Epic 1:领域模型与数据契约落地 + +目标: + +- 将高层设计中的聚合、字段、事件和权威矩阵落到实现契约。 + +Stories: + +1. 建立 `FlightOperation` 数据模型 +2. 建立 `Turnaround` 数据模型 +3. 建立 `MilestoneObservation` 和 `DecisionLog` 数据模型 +4. 建立 `Resource` / `ResourceAllocation` 数据模型 +5. 建立 `AlertCase` / `DataQualityFlag` 数据模型 + +验收条件: + +- 所有核心对象具备主键、唯一键、幂等键和状态字段定义 +- Published Fact 可追溯到 Observation 和 Decision + +测试关注点: + +- 主键稳定性 +- 幂等键生成 +- 配对修正一致性 + +### Epic 2:接入与标准化 + +目标: + +- 接入 SSIM、AIDX、AFTN 并形成统一内部事件模型。 + +Stories: + +1. 实现 SSIM 导入和批次标识 +2. 实现 AIDX 标准化映射 +3. 实现 AFTN / Type B 报文解析 +4. 实现标准化失败进入 DLQ +5. 实现人工复核任务创建 + +验收条件: + +- 三类输入都能进入标准化事件模型 +- 解析失败可复核、可重放、可审计 + +测试关注点: + +- 重复导入 +- 报文乱序 +- 格式错误 + +### Epic 3:Published Fact 与字段级权威治理 + +目标: + +- 实现 Observation -> Decision -> Published Fact 的治理链路。 + +Stories: + +1. 实现字段级权威矩阵加载与版本化 +2. 实现候选事实评估 +3. 实现自动裁决 +4. 实现人工裁决写入 +5. 实现 Published Fact 更新和审计 + +验收条件: + +- ALDT、AIBT、TOBT、Stand Assignment 等关键字段完成治理闭环 +- 当前值可返回来源、可信度和裁决摘要 + +测试关注点: + +- 多源冲突 +- 更正报文 +- 超窗乱序 + +### Epic 4:资源分配与冲突治理 + +目标: + +- 让资源分配具备最小可运营能力,而不是只有时间窗逻辑。 + +Stories: + +1. 建立 Resource 主数据和能力约束 +2. 实现 ResourceAllocation 软锁 / 硬锁 +3. 实现时间冲突检测 +4. 实现适配 / 状态 / 策略冲突检测 +5. 实现人工覆盖与回滚 + +验收条件: + +- 四类资源都具备分配、冲突、覆盖和审计能力 +- 冲突能明确归类并生成告警 + +测试关注点: + +- 延误引发冲突 +- 换机型 +- 资源停用 + +### Epic 5:告警、Case 和人工复核 + +目标: + +- 把“人工介入”从口头方案变成有状态可追溯流程。 + +Stories: + +1. 建立 AlertCase 状态机 +2. 建立 ReviewTask 状态机 +3. 实现 `ManualDecisionRecorded` +4. 实现 `ReviewTaskOpened / Closed` +5. 实现告警确认、关闭、抑制 + +验收条件: + +- 告警和复核都有结构化状态流转 +- 人工动作全部事件化和审计化 + +测试关注点: + +- 告警重复触发 +- 复核结果重放 +- 覆盖与回滚 + +### Epic 6:事件骨干与订阅 + +目标: + +- 构建可重放、可补偿、可隔离的标准化事件分发能力。 + +Stories: + +1. 设计 Topic 与分区策略 +2. 实现统一事件信封 +3. 实现 Outbox + CDC 发布 +4. 实现事件订阅接口 +5. 实现断线重连与游标回放 + +验收条件: + +- 对外事件以 Kafka 标准化事件为唯一源头 +- 订阅具备至少一次投递和补偿能力 + +测试关注点: + +- 重复投递 +- CDC 断点恢复 +- 消费者去重 + +### Epic 7:查询接口与权限治理 + +目标: + +- 提供只读查询,不污染事实事件路径。 + +Stories: + +1. 实现 FlightOperation 查询 +2. 实现 MilestoneObservation 历史查询 +3. 实现 ResourceAllocation 生效集查询 +4. 实现 AlertCase 查询 +5. 接入 OIDC / OAuth2 / RBAC + +验收条件: + +- 查询接口支持过滤、分页、更新时间和数据质量字段 +- 读权限和订阅权限隔离 + +测试关注点: + +- 稳定分页 +- 字段权限 +- 限流 + +### Epic 8:平台、容灾与观测 + +目标: + +- 为 SLO 提供可验证支撑,而不是口头承诺。 + +Stories: + +1. 实现 PostgreSQL HA 和备份恢复 +2. 实现 Kafka 副本和保留策略 +3. 实现 CDC / 发布器观测 +4. 建立端到端延迟、DLQ、幂等命中率监控 +5. 完成容灾与回放演练 + +验收条件: + +- RTO / RPO 有演练记录 +- P95 延迟、对账、订阅补偿可验证 + +测试关注点: + +- DB 切换 +- 事件堆积 +- 订阅重连 + +## 4. Story 模板 + +每个 story 必须具备: + +- 背景 +- 范围 +- 非范围 +- 接口 / 数据影响 +- 验收条件 +- 回归风险 +- 测试点 + +## 5. 建议实施顺序 + +1. Epic 1:领域模型与数据契约落地 +2. Epic 2:接入与标准化 +3. Epic 3:Published Fact 与字段级权威治理 +4. Epic 4:资源分配与冲突治理 +5. Epic 5:告警、Case 和人工复核 +6. Epic 6:事件骨干与订阅 +7. Epic 7:查询接口与权限治理 +8. Epic 8:平台、容灾与观测 + +## 6. 进入开发前的 Gate + +- 高层设计、技术栈、ADR 无结构性冲突 +- 字段级权威矩阵完成首版 +- 事件 schema 草案完成首版 +- 最小部署拓扑完成首版 +- Epic 级拆解得到负责人和初步估算 diff --git a/airport-wiki/concepts/aodb/AODB 最小部署拓扑草案.md b/airport-wiki/concepts/aodb/AODB 最小部署拓扑草案.md new file mode 100644 index 0000000..c523e84 --- /dev/null +++ b/airport-wiki/concepts/aodb/AODB 最小部署拓扑草案.md @@ -0,0 +1,176 @@ +# AODB 最小部署拓扑草案 + +## 1. 文档定位 + +本文档给出 AODB MVP 的最小部署拓扑、关键高可用策略和恢复思路,用于支撑高层设计中的 SLO 和上线门禁。 + +## 2. 目标 + +- 以单机场私有化部署为前提 +- 优先满足当前态统一、事件不丢、审计可回放 +- 用最少组件完成可恢复、可观测、可演练的运行形态 + +## 3. 逻辑拓扑 + +```text + +-------------------------+ + | External Systems | + | SSIM / AIDX / AFTN | + +------------+------------+ + | + v + +-------------------+ + | Kong Gateway | + +-------------------+ + | + +---------------+----------------+ + | | | + v v v + +----------------+ +----------------+ +------------------+ + | Flight Service | | Milestone Svc | | External API Svc | + +----------------+ +----------------+ +------------------+ + | | | + +-------+-------+----------------+ + | + v + +----------------------+ + | PostgreSQL/Timescale | + | Current + Audit + | + | Outbox | + +----------+-----------+ + | + v + +---------------+ + | CDC/Publisher | + +-------+-------+ + | + v + +-------+ + | Kafka | + +---+---+ + | + +----------+-----------+ + | | + v v + +----------------+ +----------------+ + | Resource Svc | | Alert Service | + +----------------+ +----------------+ + + +----------------+ + | Redis Cache | + +----------------+ + + +-------------------------------+ + | Prometheus / Grafana / Loki | + +-------------------------------+ +``` + +## 4. 部署分区建议 + +### 4.1 状态层 + +- PostgreSQL / TimescaleDB +- Kafka +- Redis + +要求: + +- 与无状态服务分离部署 +- 具备独立备份和恢复策略 + +### 4.2 无状态业务层 + +- Flight Operation Service +- Milestone Service +- Resource Service +- Alert Service +- External API Service +- CDC / Publisher + +要求: + +- 多副本 +- 滚动升级 +- 配置和密钥外置 + +### 4.3 平台观测层 + +- Kong +- Keycloak +- Prometheus +- Grafana +- Loki + +## 5. 高可用建议 + +### 5.1 PostgreSQL / TimescaleDB + +- 主备部署 +- 定期全量备份 + WAL / PITR 能力 +- 演练主备切换 + +### 5.2 Kafka + +- 多 broker +- `replication factor >= 3` +- `min ISR >= 2` +- 消费位点外部可追踪 + +### 5.3 Redis + +- 主从或哨兵 +- 缓存失效不应影响核心写链路 + +### 5.4 无状态服务 + +- 至少 2 副本 +- 健康检查 + 自动重启 +- 发布器必须支持重复执行幂等 + +## 6. 最小恢复策略 + +### 6.1 数据库故障 + +- 切换到备实例 +- 根据最近备份和 WAL 进行恢复 +- 恢复后执行 Published Fact 与 Outbox 对账 + +### 6.2 Kafka 堆积或单 broker 故障 + +- Broker 恢复后消费者追赶 +- 重点检查订阅延迟、DLQ 率、CDC 积压 + +### 6.3 CDC / Publisher 中断 + +- 根据 Outbox 位点断点续传 +- 保证重复发布不产生重复副作用 + +### 6.4 查询层异常 + +- 核心写链路不中断 +- 对外查询可降级,但订阅恢复后必须可补偿 + +## 7. 关键观测指标 + +| 指标 | 含义 | +| --- | --- | +| ingest_to_publish_latency_p95 | 接入到发布的 P95 延迟 | +| outbox_backlog | Outbox 堆积量 | +| cdc_publish_retry_count | 发布重试次数 | +| kafka_consumer_lag | 消费滞后量 | +| dlq_rate | 解析失败和旁路率 | +| conflict_mttr | 冲突平均处置时间 | +| review_task_open_count | 未关闭复核任务数 | + +## 8. 上线前必须演练 + +1. PostgreSQL 主备切换 +2. Kafka 单 broker 故障恢复 +3. CDC 中断和断点恢复 +4. 订阅端断线重连与游标补偿 +5. 关键字段回放抽检 + +## 9. 与高层设计的关系 + +- 本文档细化 `开源机场运营数据库(AODB)高层设计文档.md` 中的部署与 SLO 章节。 +- 它不是最终部署手册,但必须足以支撑架构评审和上线门禁定义。 diff --git a/airport-wiki/concepts/aodb/AODB 高层设计修订计划.md b/airport-wiki/concepts/aodb/AODB 高层设计修订计划.md new file mode 100644 index 0000000..ff3f77b --- /dev/null +++ b/airport-wiki/concepts/aodb/AODB 高层设计修订计划.md @@ -0,0 +1,79 @@ +# AODB 高层设计修订计划 + +## 1. 修订目标 + +本轮修订目标不是继续扩展概念,而是把 AODB 设计收敛成可以进入开工评审的版本: + +- 收缩 MVP,避免首期过载 +- 锁定领域边界和写主归属 +- 明确事实分层和字段级权威矩阵 +- 将资源冲突从单一时间窗问题升级为可运营模型 +- 分离查询接口与事件订阅 +- 补齐部署、容灾、审计和演练要求 + +## 2. 当前主要问题 + +1. MVP 范围过重,和目标机场规模、交付周期不匹配。 +2. 服务边界偏描述性,未锁定写主和聚合边界。 +3. 缺少 `Turnaround` 等关键领域对象。 +4. SSOT 仅有原则,缺少 Observation / Decision / Published Fact 分层。 +5. 资源模型过薄,无法表达适配、冻结、软硬锁定等真实约束。 +6. SLO 未充分映射到部署和容灾设计。 + +## 3. 分阶段任务 + +### 3.1 阶段 1:收缩范围 + +- 重写需求文档中的 MVP / P1 / P2 分层 +- 在高层设计文档中删去首期不需要的平台化能力 +- 在技术栈文档中区分 MVP 主选和后续启用组件 + +### 3.2 阶段 2:重构领域边界 + +- 新增聚合边界表 +- 锁定 Flight 当前态唯一写主 +- 引入 `Turnaround` 作为首期核心对象 + +### 3.3 阶段 3:补齐事实模型 + +- 引入 Observation / Decision / Published Fact 三层模型 +- 增加字段级权威矩阵 +- 明确人工覆盖和更正语义 + +### 3.4 阶段 4:补齐资源与事件模型 + +- 扩展 Resource / ResourceAllocation 模型 +- 建立冲突分类 +- 规范事件分类、事件归属和消费者契约 + +### 3.5 阶段 5:补齐部署与 ADR + +- 增加最小部署拓扑、SLO 映射和容灾约束 +- 写入关键 ADR,固化设计取舍 + +## 4. 决策记录索引 + +- `adr/ADR-001 MVP 不引入 Flink.md` +- `adr/ADR-002 Kafka 作为唯一事件骨干.md` +- `adr/ADR-003 事实分层模型.md` +- `adr/ADR-004 FlightOperation 写主归属.md` +- `adr/ADR-005 Turnaround 独立建模.md` +- `adr/ADR-006 资源锁定模型.md` +- `adr/ADR-007 查询与订阅分离.md` +- `adr/ADR-008 Outbox 与 CDC.md` +- `adr/ADR-009 PostgreSQL HA.md` +- `adr/ADR-010 人工裁决事件化.md` + +## 5. 下层设计文档 + +- `AODB 实施 Backlog.md` +- `AODB 字段级权威矩阵.md` +- `AODB 事件 Schema 草案.md` +- `AODB 最小部署拓扑草案.md` + +## 6. 完成标准 + +- 三份核心文档在范围、技术栈和边界定义上相互一致 +- 关键设计取舍全部具备 ADR +- 文档可直接支持任务拆解、测试设计和架构评审 +- 下层设计文档足以支撑实现前的细化评审 diff --git a/airport-wiki/concepts/aodb/adr/ADR-001 MVP 不引入 Flink.md b/airport-wiki/concepts/aodb/adr/ADR-001 MVP 不引入 Flink.md new file mode 100644 index 0000000..999723c --- /dev/null +++ b/airport-wiki/concepts/aodb/adr/ADR-001 MVP 不引入 Flink.md @@ -0,0 +1,24 @@ +# ADR-001 MVP 不引入 Flink + +## 状态 + +Accepted + +## 背景 + +首期目标是完成单机场 AODB 核心闭环,规模为 500 万至 3000 万旅客机场,优先解决当前态统一、资源冲突和审计问题。 + +## 决策 + +MVP 不引入 Flink。首期只保留 Kafka 事件骨干和应用服务内流式处理逻辑。预测、CEP 和复杂有状态计算推迟到 P1。 + +## 原因 + +- 首期复杂度应优先让位于交付确定性。 +- 预测与复杂流处理不是首期闭环前提。 +- Flink 会显著提高部署、运维和故障恢复复杂度。 + +## 后果 + +- MVP 中实时计算能力受限。 +- 事件契约和聚合边界必须为未来引入 Flink 预留演进空间。 diff --git a/airport-wiki/concepts/aodb/adr/ADR-002 Kafka 作为唯一事件骨干.md b/airport-wiki/concepts/aodb/adr/ADR-002 Kafka 作为唯一事件骨干.md new file mode 100644 index 0000000..744ebbc --- /dev/null +++ b/airport-wiki/concepts/aodb/adr/ADR-002 Kafka 作为唯一事件骨干.md @@ -0,0 +1,24 @@ +# ADR-002 Kafka 作为唯一事件骨干 + +## 状态 + +Accepted + +## 背景 + +AODB 需要支撑事件可回放、订阅分发、补偿和审计。 + +## 决策 + +Kafka 作为唯一事实事件骨干。所有对外事件订阅都以 Kafka 上的标准化事件为源头,禁止多路事件源头并存。 + +## 原因 + +- 统一重放和补偿语义。 +- 避免“写库成功但未发布”或“已发布但未落库”的治理空洞。 +- 降低外部消费者理解成本。 + +## 后果 + +- 事件可靠发布必须依赖 Outbox + CDC。 +- 查询 API 不能被下游误当作事件事实源。 diff --git a/airport-wiki/concepts/aodb/adr/ADR-003 事实分层模型.md b/airport-wiki/concepts/aodb/adr/ADR-003 事实分层模型.md new file mode 100644 index 0000000..9e56e64 --- /dev/null +++ b/airport-wiki/concepts/aodb/adr/ADR-003 事实分层模型.md @@ -0,0 +1,24 @@ +# ADR-003 事实分层模型 + +## 状态 + +Accepted + +## 背景 + +AODB 需要同时处理多源观测、字段裁决和对外权威事实发布。 + +## 决策 + +采用 `Observation / Decision / Published Fact` 三层模型。 + +## 原因 + +- 让 SSOT 真正表示“经过治理后发布的事实”。 +- 保证原始观测、人工覆盖和当前值三者不互相污染。 +- 便于审计、回放和责任归因。 + +## 后果 + +- 数据模型和事件模型会更明确,但设计和实现复杂度略有上升。 +- Published Fact 的任何变更都必须可追溯到 Observation 和 Decision。 diff --git a/airport-wiki/concepts/aodb/adr/ADR-004 FlightOperation 写主归属.md b/airport-wiki/concepts/aodb/adr/ADR-004 FlightOperation 写主归属.md new file mode 100644 index 0000000..d7bd994 --- /dev/null +++ b/airport-wiki/concepts/aodb/adr/ADR-004 FlightOperation 写主归属.md @@ -0,0 +1,24 @@ +# ADR-004 FlightOperation 写主归属 + +## 状态 + +Accepted + +## 背景 + +原方案中 Flight、Milestone、Resource、Alert 边界存在写入重叠风险。 + +## 决策 + +Flight 当前权威态只能由 `Flight Operation Service` 写入,其他服务只能产生观测、候选事实、资源事实或告警事实。 + +## 原因 + +- 避免多个服务共同修改同一当前态。 +- 降低一致性和回放复杂度。 +- 方便将 Published Fact 聚合到单一领域对象。 + +## 后果 + +- Milestone 和 Resource 服务必须通过事件影响 Flight 当前态。 +- Flight Service 需要承担更明确的聚合协调责任。 diff --git a/airport-wiki/concepts/aodb/adr/ADR-005 Turnaround 独立建模.md b/airport-wiki/concepts/aodb/adr/ADR-005 Turnaround 独立建模.md new file mode 100644 index 0000000..5af54b8 --- /dev/null +++ b/airport-wiki/concepts/aodb/adr/ADR-005 Turnaround 独立建模.md @@ -0,0 +1,24 @@ +# ADR-005 Turnaround 独立建模 + +## 状态 + +Accepted + +## 背景 + +仅以单航班建模无法充分表达到离港配对、机尾号上下文和资源联动。 + +## 决策 + +将 `Turnaround` 作为首期核心领域对象,引入最小独立建模。 + +## 原因 + +- 支撑航班配对(Linking)需求。 +- 提高资源分配和时序解释能力。 +- 为换机、延误联动和周转分析提供上下文。 + +## 后果 + +- 文档和模型复杂度上升。 +- 配对修正和不完整配对需要额外的事件和审计语义。 diff --git a/airport-wiki/concepts/aodb/adr/ADR-006 资源锁定模型.md b/airport-wiki/concepts/aodb/adr/ADR-006 资源锁定模型.md new file mode 100644 index 0000000..724d3f9 --- /dev/null +++ b/airport-wiki/concepts/aodb/adr/ADR-006 资源锁定模型.md @@ -0,0 +1,24 @@ +# ADR-006 资源锁定模型 + +## 状态 + +Accepted + +## 背景 + +单纯的资源时间窗分配无法表达建议分配、已确认分配和人工强制覆盖。 + +## 决策 + +ResourceAllocation 支持 `soft lock` 和 `hard lock` 两种锁定语义。 + +## 原因 + +- 表达自动建议和人工强制分配的区别。 +- 支持冲突检测、覆盖和回滚的可解释性。 +- 为未来优化排班预留空间。 + +## 后果 + +- 冲突检测和分配逻辑需要区分锁定强度。 +- 人工覆盖必须伴随审计和事件输出。 diff --git a/airport-wiki/concepts/aodb/adr/ADR-007 查询与订阅分离.md b/airport-wiki/concepts/aodb/adr/ADR-007 查询与订阅分离.md new file mode 100644 index 0000000..7f3b59c --- /dev/null +++ b/airport-wiki/concepts/aodb/adr/ADR-007 查询与订阅分离.md @@ -0,0 +1,24 @@ +# ADR-007 查询与订阅分离 + +## 状态 + +Accepted + +## 背景 + +将 GraphQL Subscription 或查询层直接作为事实流会混淆读取和事件分发语义。 + +## 决策 + +对外查询接口和事件订阅接口分离设计。 + +## 原因 + +- 查询和事件分发的稳定性、回放、限流语义不同。 +- 便于明确外部消费者的消费契约。 +- 降低把查询接口误当权威事件骨干的风险。 + +## 后果 + +- 需要独立设计事件订阅网关或分发适配层。 +- API 文档要分别描述查询和订阅契约。 diff --git a/airport-wiki/concepts/aodb/adr/ADR-008 Outbox 与 CDC.md b/airport-wiki/concepts/aodb/adr/ADR-008 Outbox 与 CDC.md new file mode 100644 index 0000000..8ca4928 --- /dev/null +++ b/airport-wiki/concepts/aodb/adr/ADR-008 Outbox 与 CDC.md @@ -0,0 +1,24 @@ +# ADR-008 Outbox 与 CDC + +## 状态 + +Accepted + +## 背景 + +AODB 必须避免“写库成功但没发事件”或“发了事件但没落库”。 + +## 决策 + +采用 `Outbox Pattern + CDC` 作为写库与发事件一致性策略。 + +## 原因 + +- 能把数据库状态变化和事件发布绑定到同一事务边界。 +- 适合首期 Kafka 作为唯一事件骨干的架构。 +- 支持失败重试、断点恢复和事件回放。 + +## 后果 + +- 需要部署 CDC / 发布器组件。 +- 发布流程和 Outbox 堆积需要专门监控。 diff --git a/airport-wiki/concepts/aodb/adr/ADR-009 PostgreSQL HA.md b/airport-wiki/concepts/aodb/adr/ADR-009 PostgreSQL HA.md new file mode 100644 index 0000000..7333952 --- /dev/null +++ b/airport-wiki/concepts/aodb/adr/ADR-009 PostgreSQL HA.md @@ -0,0 +1,24 @@ +# ADR-009 PostgreSQL HA + +## 状态 + +Accepted + +## 背景 + +Published Fact、审计和 Outbox 都依赖 PostgreSQL,数据库可用性直接决定系统可用性。 + +## 决策 + +MVP 必须采用 PostgreSQL 高可用部署,并具备备份恢复和 PITR 或等价能力。 + +## 原因 + +- 满足 RTO / RPO 目标。 +- 为审计、重放和一致性提供稳定基础。 +- 避免首期把可靠性寄托在应用层补偿上。 + +## 后果 + +- 部署和运维门槛上升,但这是首期必须承担的复杂度。 +- 需要单独演练主备切换和恢复流程。 diff --git a/airport-wiki/concepts/aodb/adr/ADR-010 人工裁决事件化.md b/airport-wiki/concepts/aodb/adr/ADR-010 人工裁决事件化.md new file mode 100644 index 0000000..3ce5262 --- /dev/null +++ b/airport-wiki/concepts/aodb/adr/ADR-010 人工裁决事件化.md @@ -0,0 +1,24 @@ +# ADR-010 人工裁决事件化 + +## 状态 + +Accepted + +## 背景 + +AODB 中数据冲突、资源覆盖和解析失败都可能需要人工参与。 + +## 决策 + +所有人工裁决、人工覆盖和人工复核动作必须事件化和审计化,禁止仅通过数据库备注或日志留痕。 + +## 原因 + +- 人工动作是业务事实的一部分。 +- 需要对外解释当前值为何成立。 +- 便于回放、对账和合规审计。 + +## 后果 + +- Case 流程和审计模型需要更完整。 +- 首期必须实现最小人工复核状态机。