Skip to content

服务持久化与重载语义参考 ​

本文档梳理 Aalis 内置 / 一方插件提供的关键服务在 plugins.bounce(id)、 依赖变化触发的 recompute()、整进程 restart() 三种生命周期事件下的状态保持情况,供 插件作者与运维人员判断"我能不能热重载这个插件"。

概念 ​

  • 进程内态(in-memory):仅存于运行时内存,重启即丢。bounce 时若服务 归属的插件被重新 apply,其内存态会重建为空。
  • 磁盘 / DB 态(persistent):通过 storage 服务、SQLite / MongoDB / 文件 落盘,重建后会从磁盘读回。
  • bounce-safe:服务所属插件被 app.plugins.bounce 重新激活后,对外可见的 状态能在合理时间内恢复(要么数据从磁盘 / 上游回流,要么内存重建后下游会 自然重新填充)。

服务状态对照表 ​

服务名提供方插件内存态内容持久化来源bounce 是否保留说明
app@aalis/coreApp 实例n/an/a由 host 注入,永不 bounce
plugins@aalis/corePluginManagern/an/a由 host 注入,永不 bounce
host-config@aalis/runtime(宿主)配置文档与密钥存储aalis.config.yaml、secrets.yamln/a由宿主在根上提供,永不 bounce;改插件配置用 applyPluginConfig(运行态、文档、密钥与落盘一步完成);启停等管理动作不写文档,要跨重启保留由调用方写文档后 save()
hooks@aalis/plugin-hooks钩子链n/a否(由登记方重建)bounce 时依赖它的插件先关闭,再按拓扑序重新激活并重新登记,链序与冷启动相同
contributions@aalis/plugin-contributions贡献登记表n/a否(由登记方重建)同上;collect 顺序只由全局键决定,重建后不变
commands@aalis/plugin-commands命令注册表(Map)n/a否bounce 后由各插件 apply 时重新 register
agent@aalis/plugin-agentpreprocessor / processor 列表n/a否同上,依赖下游插件 apply 时回注
tools@aalis/plugin-tool-systemtool 定义 Mapn/a否同上
webui-server@aalis/plugin-webui-server页面与提示的登记表n/a否bounce 后下游插件经业务层的 definePage / notify 由 registrar 跟随重挂;owner 的布局记录在插件数据里,不随之丢失
doctor@aalis/plugin-doctorlastReport 单例n/a否重载后报告丢失,需重新 runChecks
scheduler@aalis/plugin-scheduler任务调度状态data/scheduler-jobs.json是(持久部分)bounce 后从 JSON 读回;运行中的 timer 会重建
authority@aalis/plugin-authority角色规则配置文件是规则随配置一起回填
session-manager@aalis/plugin-session-manager活跃 session Map视下游 memory 插件部分历史走 memory 服务,活跃句柄丢失需重建;会话表跟随 memory 选中的那一家,换后端时先把未落盘的变更写回旧后端,再从新后端读表整体替换(不跨后端合并)
memory@aalis/plugin-memory-sqlite / -mongodb / -summary / -inmemoryLRU / 缓存SQLite / MongoDB(内存版除外)是(持久驱动)/ 否(inmemory)inmemory 驱动 bounce 即清空
vectorstore@aalis/plugin-vectorstore-lancedb / -flat索引句柄data/lancedb/ / 平铺文件是句柄重建后数据可用
embedding@aalis/plugin-embedding-*HTTP clientn/an/a(无状态)重建即可用
llm-*各 LLM provider 插件HTTP clientn/an/a同上
storage@aalis/plugin-storage-localfs handles磁盘是文件系统抽象,bounce 安全
tools.search@aalis/plugin-tool-search配置n/an/a重建即可用
tools.code-runner@aalis/plugin-tool-code-runnerrunner 进程池n/a否重建会创建新进程池,正在执行的任务会丢失
tools.browser@aalis/plugin-tool-browserPlaywright 会话n/a否重建会断开当前浏览器会话
todo-list@aalis/plugin-todo-list任务列表视配置(默认内存)否(默认)默认内存态,bounce 即丢
user-profile@aalis/plugin-user-profileprofile 缓存memory 服务是走 memory 服务持久化

重载注意事项 ​

provider bounce 时,此刻 required 选中它的 active 下游(传递闭包)随之重启:并入同一批先收尾、先关,provider 重新激活后按拓扑序重新激活;有后备提供者时同样重启,不在空档里切到后备。其余下游不重启:消费者的业务句柄每次访问都重新解析到选中的那一家;有状态接线(SDK 句柄、订阅)用 follow 跟随重建。登记型能力(工具、页面、命令)由描述符的 registrar 在提供者换人时整体重挂。

  1. bounce 连带重启 required 下游:bounce(target) 拆掉 target 的激活,其 provided 服务从容器移除;此刻 required 选中 target 的 active 下游同批重启,其进程内态随重启丢失。其余下游目标态不变(optional 上下线不改变目标态),业务句柄下一次访问打到新选中的那一家;follow / registrar 负责交接。

  2. 避免 bounce 持有外部连接的插件:上表中标注 "重建即可用" 的插件可以 安全 bounce;标注 "进程池 / 浏览器会话" 的服务 bounce 会断开外部资源, 建议先停止依赖工作流再重载。

  3. 配置变更走 updateConfig 而非换代码:前者换上新的运行配置后 bounce,只改运行态;要跨重启保留,改用 host-config 的 applyPluginConfig,它在内部调 updateConfig,同时写文档、拆出密钥并落盘;换代码走 unload + register(宿主热加载见 @aalis/runtime 的 PluginLoader.reload 与 plugin-source 的 rescan())。

  4. 多实例插件 (name:suffix) 仅作用于指定 instanceId:同 module 的其 他实例不受影响,需各自调用 bounce(instanceId)。

  5. integration / e2e 推荐在 bounce 后等 plugins.idle():直接调用 bounce 之后立即 assert 服务可用会读到拆卸中间态。plugins:changed 在 recompute 收敛时发出,同样可用。

整份快照的加载失败 ​

激活时整份读入、之后整份回写的插件(scheduler 动态任务、workflow 运行历史与 once 记账、flow-control 禁言表、authority 用户等级、vectorstore-flat 向量库),加载结果只分三种:

  • 不存在:@aalis/api-storage 的 isStorageNotFound(err) 为真,按全新处理,照常写入。
  • 读取成功:读取、解析、结构校验都通过,照常写入。
  • 读不懂:其余一切情况,包括其它读取错误(含存储提供者的「未知存储根」)、解析失败、合法 JSON 但结构不对。本次运行拒绝整份写入并告警,改动只在内存生效,原文件保持原样;重新读取(storage 换人时经 follow 重读,或重启)时重新判定。

实现上:读取与解析分两段,解析报错不进入「不存在」判据;结构不对抛错归入「读不懂」,不当空处理;写入闸放在串行写链里,等进行中的读取完成后再判;从记账派生的行为(workflow 的 once)在「读不懂」时不据空状态执行。

增量重载的 API 速查 ​

ts
// dispose + 重新 apply(不重新 import:从磁盘重载代码是宿主的事,见 @aalis/runtime 的 PluginLoader.reload)
await plugins.use.bounce('@aalis/plugin-foo');

// 配置变化后的标准入口:换上新配置再按 bounce 重启
await plugins.use.updateConfig(instanceId, newConfig);

全局收敛(recompute)由 PluginManager 内部驱动,不在 PluginManagerService 接口上;app.plugins 对外也只是这个接口。管理类插件在 uses 里声明 pluginsService。

文档对应 dev@c4e046e41,core 0.21.0,构建于 2026-11-02
基于 MIT 许可发布