Skip to content

Latest commit

 

History

History
173 lines (126 loc) · 11.8 KB

File metadata and controls

173 lines (126 loc) · 11.8 KB

Graft 运行时组合与资源治理设计

1. 目的

本文固定 Graft Runtime、Module、Provider、Agent、Runner、Task Runtime 与 realtime 运行面在组合时必须遵守的三项原则:

  1. 每个运行时资源都必须有可追踪的创建者、owner 和 disposer。
  2. capability 的可见性必须受稳定边界控制,不能默认成为全局可见服务。
  3. 每个组合单元必须声明依赖、暴露 capability 和清理责任。

本文不把 Graft 改造成动态插件平台。当前 compile-time module registry、显式 DI、Task/Submission authority 和 Provider 生命周期仍是唯一基线。

2. 适用对象与非对象

适用对象:

  • server/internal/app 的 Runtime 与 core resources;
  • server/modules/* 的 Module、collector、event consumer、cron job 和 realtime stream;
  • 后续 compile-time Provider、独立 Agent、Runner 与 Integration;
  • Task Runtime 的 worker、Stage executor 和 operation-scoped external resource;
  • WebSocket/SSE gateway、topic subscription 与 observer。

不适用对象:

  • Codex 或仓库 .agents/skills/**;它们是开发工具,不是 Graft 产品运行时 Skill;
  • 临时纯函数、请求内短期值和 PostgreSQL 事务本身;它们继续由调用栈或 context.Context 直接拥有;
  • runtime filesystem scan、动态 module/Provider discovery、第三方 marketplace、HMR 或热卸载。

3. 术语与 ownership

概念 含义 例子
runtime resource 需要显式释放、停止、注销或等待退出的运行时实体 goroutine、ticker、event subscription、WebSocket、Docker client、worker pool
creator 实际创建资源的代码边界 Module Boot、Task Runtime Start、gateway handler
owner 对资源存活、失败、观测和最终清理负责的唯一 authority Module、Task Runtime、Agent process、realtime subscription
disposer 可重复调用且尽最大努力的释放操作 Stop(ctx)Close(ctx)、unsubscribe closure、Shutdown(ctx)
capability 一个受 typed contract 约束的业务或平台能力 moduleapi.TaskService、Provider-neutral port
composition unit 能声明依赖、暴露 capability 与清理责任的稳定单元 Module、Provider、Agent、Runner、Task Runtime

owner 不等于调用者:调用方可以消费 capability,但不得接管其资源生命周期或持久化事实。一个资源只能有一个 owner;共享资源必须由其 owner 提供受控使用接口,而不是转移关闭权。

4. Runtime 模型

Application Runtime
  |
  +-- compile-time Module registry
  |     +-- Module lifecycle scope
  |           +-- module capability / route / job declarations
  |           +-- module-owned collectors, subscriptions and clients
  |
  +-- Task Runtime
  |     +-- persisted Submission / Task / Stage facts
  |     +-- worker and execution scopes
  |
  +-- Provider / Runner / Agent boundaries
  |     +-- compile-time Provider lifecycle
  |     +-- independent Agent process lifecycle
  |
  +-- Core runtime services
        config | logger | event | realtime | permission | service container

这不是 Agent -> Task -> Plugin 的通用父子 Context 树:Agent 是独立进程与身份边界,Task 是持久化执行事实,Module 是编译期应用能力。只有真实的取消、资源从属和释放顺序才建立 scope 关系。

5. 资源生命周期规则

5.1 创建、停止与失败

  • Register 只声明 capability、route、permission、job、event consumer 和配置定义;不得启动长期资源。
  • Boot 启动 Module-owned runtime resource,必须使用 Runtime 注入的 lifecycle context 或由 owner 从它派生的 context。
  • Shutdown 以 Runtime 注入的有界 shutdown context 反向停止资源;不得用 context.Background() 绕过关闭语义。
  • durable event Dispatcher 是 Runtime-owned core resource,不属于任一 Module;它可以使用独立于 runCtx 的 process-lifetime parent,以便在请求取消或监听器异常后 drain 已接收事件,但必须由 Runtime 的有界 shutdown context 显式停止。该独立 parent 不是逃逸关闭责任的理由。
  • 独立 Agent、Provider、Runner 与 Task Runtime 必须有同等明确的 StartStopClose owner;它们不得自建第二套启动、任务、配置或恢复机制。
  • 启动失败时 creator 必须清理本次已创建资源;Runtime 继续清理此前成功启动的 owner。关闭失败必须记录并聚合,不能阻止后续 cleanup。

5.2 可追踪性

每个长期资源必须能从代码和日志回答:

  • 创建者、owner 与所属 composition unit;
  • 父 lifecycle context 或 operation identity;
  • 开始、停止、失败和 cleanup 结果;
  • 停止 timeout、未完成工作和恢复语义;
  • 是否有持久化事实,以及其 canonical owner。

对于 goroutine、timer、subscription、observer、WebSocket 和外部 client,创建点必须保留或注册 idempotent disposer。调用方不得只保留裸 channel、callback 或全局 map 引用而失去注销路径。

5.3 Event、realtime 与 timer

  • 同步 in-process EventBus 只是本地 observer,不是 durable event、Task queue 或外部 message broker;当前 MemoryBus 选择 application-lifetime owner,不提供注销或关闭接口。订阅 handler 必须同步、短时且不得隐藏创建后台资源;需要长期运行的工作必须回到 owning Module/Runtime 的显式 Boot/Shutdown
  • durable event consumer 在 Register 声明、由 dispatcher 统一启动和关闭;consumer 不得私自启动 delivery worker。
  • realtime subscription 和 topic observer 必须返回一次性可调用的取消函数;stream owner 在最后订阅者离开、Module Shutdown 或 gateway 关闭时注销 observer 并等待相关 goroutine。
  • cron registry 只登记声明;scheduler owner 负责实际调度器的启动、停止和 job cleanup。业务模块不得直接引入独立 scheduler。

6. Capability 可见性与依赖

6.1 默认规则

  • Module 内部实现、repository、ORM client、storeent、Agent 私有 transport、Provider SDK 和 runtime resource 默认不可跨边界访问。
  • 跨模块 capability 只能进入 server/internal/moduleapi/**;平台 typed contract 只能进入 server/internal/contract/**;外部 provider-neutral 能力仅在经过 boundary review 后进入 server/internal/ports/**
  • 容器只能解析已显式注册的稳定 capability。容器不是业务依赖的万能入口,也不授权任意 Module 持有全部 core service。
  • HTTP、MCP、realtime 与 web 只消费其已有契约和授权范围,不因为某个 capability 已注册就默认可访问。

6.2 声明方式

composition unit 的声明必须区分:

声明 owner 当前落点
module identity、module dependencies、builder compile-time ModuleSpec server/internal/module 与 generated registry
required / exposed cross-module capability composition unit + moduleapi owner Builder / Register 的显式 typed registration
configuration owner 与 immutable/startup policy owning core/module/provider config governance 与 definition registry
route、permission、menu、event/job/realtime topic owning module/core boundary Register phase 的对应 registry
runtime resource 与 disposer 创建它的 owner Boot/Start/handler 内的 owner state

Module dependency 解决启动排序;capability dependency 解决实际协作。两者不得互相替代:没有 capability contract 时不能仅靠依赖顺序直接 import 对方内部实现;没有 module dependency 时也不能靠一次成功的 Resolve 隐藏启动顺序要求。

Phase 3 的最小声明载体是 server/internal/module.Spec

  • RequiredCapabilitiesExposedCapabilities 使用 module.TypedCapability[T]() 生成 typed contract key;key 由 Go 类型派生,不接受字符串 service name。
  • ConfigurationOwner 只标识配置定义的 canonical owner,不触发读取、重载或拓扑变更。
  • Resources 记录 owner 已创建的长期资源及其既有 disposer 名称;它是可审计 metadata,不是通用 Scope 或自动 cleanup registry。
  • RuntimeMetadata 只读投影这些声明,供诊断与 conformance 使用;实际 capability 注册/解析继续沿用显式 container 与 moduleapi contract。

Provider、Agent、Runner 与 Task Runtime 可以复用同一声明语义,但不得把它们投影成 Module、共享 Task 状态或新增全局 registry。局部健康只允许使用 ReadyDegradedUnavailable 三态,故障仍由 capability owner 解释,不能改写 Runtime、Task/Submission 或 Agent ledger 的事实 authority。

7. Scope 的最小边界

Graft 不引入全局动态 Context hierarchy。只在下列真实资源边界创建窄 scope:

Scope owner 负责 不负责
Module lifecycle scope Module / Runtime module background resource、disposer、shutdown deadline Task persisted state、其它 Module 私有资源
Task execution scope Task Runtime Stage cancellation、executor resource、operation log Module lifecycle、Task state mutation authority
Realtime subscription scope gateway / stream owner ticket、topic、observer、connection/stream cleanup module business state
Agent process scope Agent executable identity、transport、heartbeat、process shutdown server-side Task/Submission truth
Provider operation scope Provider / Runner external client/session、operation cleanup、degraded result second task state machine

新增 scope 之前必须证明:至少两个资源需要共同取消/释放,且现有 Module、Task、subscription 或 Agent owner 无法清晰表达从属关系。否则保持局部显式 context.Context 和 disposer。

8. 生命周期状态与动态性

当前状态分类:

对象 允许的变化 禁止的变化
Module / Provider process start/stop、配置变更后的受控 process restart runtime load/unload、HMR、动态依赖重算
TaskPlan / Stage executor binding 新 Task 使用新版本定义 修改在途 Task 的冻结计划
Agent 独立进程 restart、证书/配置 rotate 后 reconnect server 内热替换为 Module
RuntimeTarget 持久化 reconcile 与受控状态转换 以内存 reload 覆盖 binding/identity 事实
System Config cache 受控 invalidation/reload 改变 Module 拓扑或权限/路由 owner
realtime connection ticket-scoped open/close 脱离 gateway 的永久全局订阅

单个 Provider 或 capability 失败应返回 capability-local UnavailableDegraded 语义;不得把故障伪装为应用全局可用,也不得以自动 plugin reload 掩盖外部副作用或泄漏。

9. 演进与验收

实施必须按以下顺序推进:

  1. 盘点和修复现有资源 owner、disposer 与 shutdown 证据。
  2. 统一 Module、Provider、Agent、Runner、Task Runtime 的 lifecycle 清单和可观测性。
  3. 在重复需求出现后,为 Module resource 或 subscription 增加窄 scope/disposer helper。
  4. 补充 required/exposed capability 声明和 capability-local health。
  5. 只有运行时隔离、持久化状态迁移、失败回滚和运维控制都已证明需要时,才重新评估动态 enable/disable;HMR 不在当前路线中。

验收标准:

  • 每个新增长期资源有 creator、owner、disposer 和关闭测试;
  • 跨 Module capability 不泄露私有实现,也不默认扩散为全局可见服务;
  • composition unit 的依赖、公开 capability、配置 owner、生命周期与 cleanup 可从一处代码/契约追踪;
  • Task、Agent、Runner、durable event 和 realtime 仍保持各自既定 authority;
  • 不增加动态 plugin loader、第二套 DI、第二套 scheduler 或第二套 Task state machine。