Skip to content

[C294] Capability 能力注入机制重设计(破坏性一次性切换) #622

Closed

Description

@AlianBlank

背景

Capability 能力尚未上线,没有存量部署和外部调用方。按 B佬 裁定(2026-10-23),这次对能力注入机制做破坏性一次性切换:不留兼容层、不分期、不保留旧入口签名,旧机制在同一个 change 里整体删除。

保留项只按正确性和架构护栏保留:12 包拓扑、GFX0017、三条装配红线(manifest Id 唯一 / 依赖闭包失败即停 / job 全名唯一)、--AllInOne --DatabaseProvider=Sqlite 零依赖起跑、桥撤销后显式返回 DependencyUnavailable(8002)。

问题

  • 模块只有 Register 一个钩子,没有启停生命周期,桥的发布与撤销只能外泄到 AppStartUpGame。
  • 桥协议同型复制 4 份(Friend / MatchGame / MatchDomain / Session),每加一个域都要手写 holder + lease + Wiring + 组合根编排。C241 代码审查把它列为头号高风险:GFX0018 按名字清单判定,已经漏掉了 Session 这一族。
  • 服务注册按类型单键单实例,替换实现靠"组合根先 UseService、模块再 TryGetService 探测"的时序约定,探测不到就静默回退 InMemory / Empty 实现。
  • 族组合根硬编码 Online 具型,admin 组装散落在 Launcher;admin action 同名时静默覆盖。
  • 机制层事件口 CapabilityEventJob / RaiseEvent 生产零调用,业务事件另走 InMemoryEventPublisher。
  • 包级 Options 全是空类;模块构造服务时传 null,服务内 ?? new XxxOptions() 兜底,生产只能跑默认值。
  • manifest 依赖声明与代码用法不一致:7 条依赖在代码里按可选写,manifest 却声明成必选。装配过程不打日志,成环时也不列出环上的能力。
  • 调度器 tick job 没有 per-job 隔离,异常被吞且零日志,时钟不可注入。

证据

  • GameFrameX.Launcher/Online/OnlineCapabilityComposition.cs:116-213:AddOnlineCapabilities 与 BuildScannedRuntime 预置 Online 具型
  • GameFrameX.Launcher/StartUp/AppStartUpGame.cs:249-361:四桥手工 Publish / Retract
  • Capability/GameFrameX.Capability.Online.Abstractions/Bridges/:4 对 holder / lease
  • Capability/GameFrameX.Capability.Hosting.Core/CapabilityHostBuilder.cs:193-236:拓扑定序遇到第一个缺失就抛出;:213 同层顺序取决于扫描顺序
  • Capability/GameFrameX.Capability.Hosting.Core/CapabilityScheduler.cs:279:空 catch
  • Capability/GameFrameX.Capability.Hosting.AdminApi/AdminActionRegistry.cs:57:同名 action 静默覆盖
  • OnlineCompetitionCapabilityModule.cs:114、OnlineMatchmakingCapabilityModule.cs:105-106:构造服务时传 null Options
  • OnlineMatchCapabilityModule.cs:103-117、OnlineCompetitionCapabilityModule.cs:121-135、OnlineOperationsCapabilityModule.cs:138-142:声明为必选,代码按可选探测

期望行为

  1. 模块契约改为 Register / Activate / Deactivate 三段;激活中途失败时逆序回滚;桥发布、榜单预建、撮合通知订阅迁入所属模块。
  2. 桥改为机制层泛型 CapabilityBridge<T>,宿主停止时自动撤销;删除 8 个 holder / lease 文件和 4 个 Wiring。
  3. 服务注册改为描述符表(类型 + 命名 + 懒工厂 + 来源),替换实现走显式 Override<T>;删除 TryGetService 和全部探测回退。
  4. 族组合骨架 CapabilityComposition.Compose 取代 AddOnlineCapabilities;admin 组装上移到 Hosting.AdminApi,同名 action 直接失败。
  5. 两条事件通道合为机制层事件总线,topic 统一为 <族>.<域>.<事件>。
  6. 启动模板新增 ComposeCapabilitiesAsync(热更装载之后、网络监听之前);"Online" 配置段声明 EnableRoles,IsEnableOnline / IsEnableOnlineAdmin 并入该配置段。
  7. 调度器做 per-job 隔离,支持时钟注入,并输出指标。
  8. 参数默认值只在能力包 Options 内定义;装配时按"包内默认 → 配置段 Online.Settings → 代码 Configure"逐字段覆盖,再执行 Validate;未知能力 Id 或未知字段直接失败。回调按实现方分三类注入:能力间依赖、宿主扩展点、Hotfix 钩子(CapabilityHook<T>)。
  9. 依赖分必选 / 可选,在任何模块 Register 之前统一检查:
    • 必选缺失或成环:打 Error 并装配失败,所有问题一次报全。
    • 可选缺失:打 Info,写明"缺失功能「…」,不影响 … 其余功能运行"。
    • 同层按能力 Id 排序。

依赖边调整(已确认):

能力 必选 可选
online-social online-foundation —
online-matchmaking online-social —
online-match — online-assets、online-matchmaking
online-competition — online-assets、online-match
online-operations online-foundation online-assets、online-social、online-match、online-matchmaking

范围外:12 包拓扑增删、三套发现机制统一、C204 双会话、热更 ALC 钉扎、Options 运行期热改。

验收检查

  • 清理 bin/obj 后 dotnet build Server.slnx --no-incremental 0 错误、0 新增警告,GFX0017 / GFX0018 0 违规
  • 全量测试全绿;新增用例覆盖生命周期回滚、桥撤销后 8002、依赖检查(必选 Error / 可选 Info / 一次报全 / 环路路径 / 与发现顺序无关)、Options 三层覆盖与失败场景、钩子挂载 / 替换 / 释放
  • --AllInOne --DatabaseProvider=Sqlite 冒烟 0 异常;好友 120/660、匹配 420、RPS 对局结算、会话恢复四条链路走通;退出后桥全部撤销
  • 排除 online-assets 时启动成功并输出可选缺失 Info;排除 online-foundation 时启动失败,并列出全部受影响能力
  • 全仓 grep 零残留:AddOnline、UseOnline、UseService、BridgeHolder、BridgeLease、TryGetService、RaiseEvent、IsEnableOnline

Activity

  1. linear-code commented on Oct 23, 2026

    @linear-code
  2. AlianBlank commented on Oct 24, 2026

    @AlianBlank
    CollaboratorAuthor

    由 #623 完成(已合并)。PR 正文当时只写了 Linear: GFX-998,不是 GitHub 关闭关键字,因此未自动关闭,此处手工补关。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions