从 cordis 迁移
Graft 参考了 cordis 的设计:应用由插件树组成,插件发布和使用服务,树可以在运行期间变化。区别在于,Graft 没有自己的上下文对象、Effect 系统或生命周期辅助工具,而是直接使用 Effect 中已有的这些能力,只补充 Effect 尚未提供的部分。
| cordis | Graft |
|---|---|
ctx,服务作为属性访问 |
Effect 环境,通过 yield* Key 读取服务。 |
ctx.plugin(plugin, config) |
Graft.plugin(plugin, input),返回一个 fork。 |
ctx.effect()、可释放对象 |
Effect.acquireRelease、Effect.addFinalizer 和插件的 Scope。 |
inject |
inject,由编译器检查,支持可选依赖。 |
ctx.provide、ctx.set |
Graft.provide。 |
| Fiber 状态 | fork 状态:Loading、Pending、Active、Failed、Disposed。 |
fiber.update |
apply 返回的更新函数。 |
fiber.restart |
fork.restart。 |
ctx.isolate、标签 |
isolate,对服务和事件都适用。 |
ctx.intercept |
配合 Context.Reference 使用的 intercept。 |
registry.replace |
Graft.replace。 |
ctx.on、ctx.emit、serial、bail |
事件:on、emit、parallel、bail、waterfall。 |
| 使用 Standard Schema 的配置 | Effect Schema,在插件激活期间解码。 |
| 日志、定时器和文件系统插件 | Effect 的 Logger、Schedule、Clock 和 FileSystem。 |
通过 eval 执行的 !!js 标签 |
只支持 !env NAME,配置文件不会执行代码。 |
Graft 增加的能力
Section titled “Graft 增加的能力”- 依赖检查。 读取未在
inject中列出的服务会触发类型错误。 - 可选依赖。
Plugin.optional(Key)允许插件在缺少某个服务时启动。该服务出现或消失时,插件会重启。 - 固定的清理顺序。 先撤回提供方发布的服务,再停止使用这些服务的插件,最后才释放提供方的资源。参见服务撤回流程。
- 可中断的启动过程。 如果插件仍在启动时依赖就消失了,Graft 会中断启动,插件不会在已经消失的服务上完成启动。
- 带类型且保留原因的失败。 插件失败时保留完整的
Cause,并可按Schedule重试。 - 可使用服务的配置解码。 解码可以异步执行,也可以使用插件的依赖。
- 保留上下文的处理函数。 事件处理函数使用所属插件自身的服务、领域(realm)和 intercept 运行。
- 可回滚的原子替换。
Graft.replace在一个事务中完成所有插件的替换;新插件启动失败时回到旧插件。 - 在其他进程中运行插件。 Remote 让某个插件在子进程、worker 或另一台机器上运行,使用它服务的插件不必改动。
Graft 不提供的部分
Section titled “Graft 不提供的部分”- 上下文代理、mixin 和访问器。 Effect 环境和普通函数即可完成同样的工作。
- 资源树。 cordis 可以列出每个插件持有的 effect。Graft 展示 fork 树,资源级别的细节交给 Effect 的追踪工具。
让编程智能体迁移
Section titled “让编程智能体迁移”仓库提供智能体 skill,引导智能体完成迁移。migrate-cordis-plugin
改写插件、服务及其测试;migrate-cordis-app 迁移
cordis.yml、插件列表和宿主程序;graft
负责迁移之后的事:设计新插件、测试和运行。用下面的命令全部安装:
npx skills add graftland/graft