8.3 KiB
8.3 KiB
ADR-0001: 事件总线与编排载体(Event Bus & Orchestration Carrier)
Status
Accepted(2026-09-12,solo 模式用户授权代决;用户迭代期可随时推翻重议——推翻时须走本 ADR 修订 + 下游 AC 连锁复核)
Date
2026-09-12
Engine Compatibility
| Field | Value |
|---|---|
| Engine | Godot 4.7.2-stable |
| Domain | Core / Scripting(Signal/Callable/生命周期) |
| Knowledge Risk | LOW(4.x 基线稳定;4.5–4.7 变更清单零命中,godot-specialist 校验通过) |
| References Consulted | docs/engine-reference/godot/(VERSION / breaking-changes / deprecated-apis / current-best-practices);godotengine/godot#6360 |
| Post-Cutoff APIs Used | None |
| Verification Required | None(切片 88/88 冒烟已实证:双源 round_end 汇聚、可回放步骤流) |
ADR Dependencies
| Field | Value |
|---|---|
| Depends On | None |
| Enables | ADR-0003(场景结构引用本 ADR 的接线纪律);A2/B1 全部事件序类 AC 从纸面契约转为可执行 |
| Blocks | 正式工程骨架搭建(架构文档 Required ADRs 条件) |
| Ordering Note | 与 ADR-0008(切片机制正式化)并行无冲突;B1 结算触发语义以本 ADR 载体承载 |
Context
Problem Statement
A2(三事件外发)、A3(stopped 直发 round_end,双发射源)、B1(结算触发 = Waiting 相位编排点、不依赖事件到达序)之间的信号载体需要一个落地形态——GDD 层只定行为契约(A2 OQ2 / B1 OQ1 均登记为"实现期 ADR 确认项")。
Constraints
- 单线程回合制(D2 EC13);Core 层零 UI 依赖、headless 可跑(D2 Rule 7)
- 结算可回放是硬承诺(B1 Core Rule 15:禁 await、零随机)
- 事件序契约:
flag_judged<round_end全路径统一,但到达序不承载语义 - RefCounted 纯逻辑类无场景表示,无法在 .tscn 编辑器里对接信号
Requirements
- 支持 A2 三事件面 + A3 stopped 直发的双发射源汇聚
- 支持多订阅者(B1 facts 缓冲;呈现层只订 B1/runner)
- 测试可捕获事件序列(A2/B1 AC 的事件捕获断言面)
- 生命周期确定(无悬挂连接、无循环引用)
Decision
组合根直连 signal 接线 + B1 Waiting 相位触发;否决 autoload 全局事件总线。
- 信号载体:A2(RefCounted)声明并发射 GDD 三事件——
cell_revealed/flag_judged/round_end_board(GDD 概念名round_end棋盘路径的实现实名);A3 停手路径发射round_end_stopped(payload 与棋盘路径同构)。回发next_round_mode/battle_over同为 A3/B1 侧 signal。 - 接线位置:全部 signal.connect 发生在组合根(主场景 Node 的装配代码)——core↔core 无静态耦合,依赖单向由接线拓扑保证。RefCounted 无 .tscn 编辑器对接能力,组合根是唯一自然落点。
- B1 触发:订阅 A3 相位变更(→Waiting)触发结算事务;触发判定只读 A3 相位观测量与
last_round_end,不消费事件到达序(同步发射 + 双发射源的正确防御—— specialist 确认信号为同步发射、多订阅者投递序 = 连接序 FIFO)。 - 订阅纪律:呈现层永不直接订阅 A2/A3——只订 B1 步骤流 / runner(切片现状固化,防呈现层绕过编排读核心生命周期状态——切片缺陷②教训)。
Architecture Diagram
[A2 minesweeper_rules]──cell_revealed/flag_judged/round_end_board──┐
[A3 action_economy]────round_end_stopped / phase→Waiting──────────┤
▼
[组合根 main 装配接线]→[B1 battle_orchestrator]
│ 步骤流行协议
▼
[D1 视图单元(只订 B1/runner)]
Key Interfaces
- 信号均为 方法 Callable 连接(见禁令);信号参数带类型标注仅作文档,无运行时检查——payload 校验由消费侧断言承载(A2 AC 前言口径)。
- A2 事件捕获测试 API:冒烟经 signal connect 到捕获数组(AC 前言"事件捕获断言面"的落地形态)。
Alternatives Considered
Alternative 1: autoload 全局事件总线
- Description: 中心 autoload 单例持有全部具名信号,系统经总线收发。
- Pros: 解耦发射者/订阅者;全局可发现。
- Cons: 全局耦合(任何系统可达任何信号——与"依赖单向"原则冲突);单线程回合制无此需求;事件溯源变难。
- Rejection Reason: 过度设计;切片直连形态已验证且更简单。
Alternative 2: 轮询(B1 每帧查 A3 相位)
- Description: B1 在 process 中轮询 A3 相位观测量。
- Cons: 延迟(帧粒度)+ 空转;与"回合制无逐帧玩法逻辑"原则冲突。
- Rejection Reason: 无收益;信号已同步即时。
Alternative 3: 回调注册表(A2 持有 handler 列表)
- Description: A2 暴露 register(handler) API,非 signal。
- Cons: 非 GDScript 惯用;多订阅者接线繁琐;丢掉引擎信号工具链(.tscn 对接、调试器可视)。
- Rejection Reason: signal 即本用途的引擎原生方案。
Consequences
Positive
- 事件生命周期确定性优于 Node 方案:RefCounted 引用计数归零即双向自动断连,无 queue_free 帧末窗口(specialist 核实)——不存在"向半死对象发射"
- 组合根接线使依赖方向可视化、可审计;切片 88/88 已验证
Negative
- 组合根承担全部接线职责——视图单元增多时接线代码线性增长(切片 main.gd 433 行已容纳;演进为装配器函数分组即可)
- 信号同步发射的再入语义需实现者理解(本 ADR 的"不依赖到达序"即防御)
Risks
- lambda 捕获 self 的循环引用:GDScript lambda 捕获持强引用——短命 RefCounted 以捕获 self 的 lambda 连到长命发射者会延长生命周期乃至成环,自动断连永不触发 → 缓解(固化为本 ADR 静态规则):core↔core 信号连接只许方法 Callable;发射者禁止持有对订阅者的反向引用
- 信号参数无运行时类型检查 → 缓解:消费侧断言(既有 AC 口径)+ 呈现载荷 schema 成文义务(code-conventions)
GDD Requirements Addressed
| GDD System | Requirement | How This ADR Addresses It |
|---|---|---|
| a2-minesweeper-rules.md | Core Rule 2 三事件回边契约(发射面封闭);OQ2 事件外发载体 | signal 载体 + 实名映射(round_end→round_end_board)+ 组合根接线;捕获 API 承载 AC 断言面 |
| b1-settlement.md | Core Rule 2 结算触发 = Waiting 相位编排点;OQ1 事件总线载体 | 订阅 A3 相位触发、只读 last_round_end、不依赖到达序 |
| a3-action-economy.md | Rule 9 round_end 双发射源(stopped 直发、payload 同构) | round_end_stopped 独立信号,同构 payload 由组包纪律保证 |
| systems-index.md | 唯一回边裁决(A2 只外发、B4/B1 订阅) | 组合根接线拓扑 = 裁决的落地形态 |
Performance Implications
- CPU: 信号发射 = 同步调用链,回合制下每事务个位数次发射——可忽略
- Memory: 方法 Callable 弱引用目标、不延长生命周期;lambda 禁令消除成环风险
- Load Time: 无
- Network: 不适用
Migration Plan
切片即本决策的实现(core/minesweeper_rules.gd 三信号、action_economy.gd round_end_stopped、battle_orchestrator.gd 双源汇聚)——无迁移,正式化 = 把接线纪律与静态规则写入扫描域(ADR-0004)。
Validation Criteria
- A2/B1 冒烟事件捕获断言面全绿(既有 88 条覆盖)
- 静态扫描:core↔core 连接零 lambda;发射者零反向引用(ADR-0004 扫描域承载)
- 回放确定性:同种子同输入步骤流逐行相同(B1 AC-33 先例,切片已证)
Related Decisions
- ADR-0003(场景结构与组合根)、ADR-0004(测试载体与静态扫描域)
- docs/architecture/architecture.md(Data Flow §2 事件路径)