news 2026/10/1 6:02:56

OpenMuse 持久化任务引擎原理:SQL 租约、检查点与中断恢复如何做到任务永不丢失

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenMuse 持久化任务引擎原理:SQL 租约、检查点与中断恢复如何做到任务永不丢失

OpenMuse 持久化任务引擎原理:SQL 租约、检查点与中断恢复如何做到任务永不丢失

【免费下载链接】openmuseA personal agent with a browser, terminal, files, and work that keeps going built with CopilotKit and AG-UI.项目地址: https://gitcode.com/gh_mirrors/op/openmuse

OpenMuse 是一个自带浏览器、终端、文件和持续工作的个人智能体,基于 CopilotKit 与 AG-UI 构建。它的持久化任务引擎把每个任务的状态、租约和检查点都写入 SQL 数据库,即使进程崩溃、服务器重启或任务被暂停,工作也不会丢失——这就是"任务永不丢失"的核心承诺。

为什么个人智能体的任务容易"丢"?

大多数智能体的工作是"对话式"的:你发消息,它回复,对话结束状态就留在内存里。一旦进程重启,正在执行的任务、执行到一半的步骤、已经保存的中间结果全部蒸发。

OpenMuse 的解决思路很直接:任务不是内存对象,而是数据库记录。所有任务(tasks)、监控(monitors)、事件(run-events)都落在一张records表里,用 JSONB 存储,配合乐观锁(Compare-And-Swap)保证多 worker 并发下的正确性:

UPDATE records SET data = data || $patch::jsonb WHERE owner=$1 AND kind=$2 AND id=$3 AND data @> $expected::jsonb RETURNING data

这段 SQL 是整台引擎的基石——"只有当我看到的数据和我预期的完全一致时才更新",实现了无锁的并发控制。实现见 db.ts。

第一步:任务入队即持久化

当你委派一个任务时,服务端并不是"启动一个内存协程",而是先往数据库插入一条AgentTask记录(初始状态queued)。任务的完整生命周期状态定义在 agent.ts:

状态含义
queued排队等待 worker 领取
running某个 worker 持有租约,正在执行
scheduled定时任务,等待nextRunAt到期
waiting_input/waiting_approval等你补充信息或批准动作
paused/succeeded/failed/cancelled暂停 / 终态

任务创建入口在 service.ts,注意新建任务时leaseId和leaseUntil都初始化为null——没有租约的任务永远处于"可被安全领取"的状态。

核心机制一:SQL 租约(Lease)——谁持有任务说了算

后台的 TaskWorker 每秒扫描一次任务表,找出到期任务(queued、scheduled到点、running但租约已过期、waiting_approval),然后用一次 compare-and-swap 原子地"抢占"任务:

  • 生成唯一的leaseId(UUID)
  • 写入leaseUntil = now + 60s
  • 状态置为running,attempts + 1

关键代码在 worker.ts。抢占的"期望条件"包含旧的leaseId和旧的leaseUntil,意味着:

  1. 两个 worker 同时抢同一个任务,只有一个能成功(CAS 天然互斥);
  2. 租约过期后,任务自动变回"可领取"——这就是崩溃 worker 的兜底。

持有任务后,worker 还会启动一个心跳定时器(间隔为租约时长的一半,约 20 秒),不断续期leaseUntil(worker.ts)。如果心跳的 CAS 失败——说明任务被暂停、取消或被别的 worker 接管——当前执行会被立即abort,不再写任何数据。

核心机制二:检查点(Checkpoint)——每走一步就存档一次

任务执行函数(execute)拿到的不是一个"裸状态",而是一个TaskContext,其中checkpoint(patch)方法(worker.ts)做两件事:

  1. 验证租约仍在自己手里(CAS 条件里带leaseId),失败就抛出LostLeaseError;
  2. 把中间进度(state、evidence、plan、artifactIds等)合并写回数据库。

以文档填写任务为例:找到源 PDF 后立即 checkpoint(service.ts),填完表单生成副本后再 checkpoint(service.ts)。这意味着即使进程在"准备回复邮件"这一步被杀掉,下次恢复执行时直接从数据库读回"PDF 已找到、副本已生成"的状态,不会重复下载或重复填写。

执行中的每个关键节点还会写一条不可变的RunEvent记录,最终在任务详情页按时间线回放给用户(service.ts)。

核心机制三:中断恢复——崩溃、重启、被接管之后怎么办

引擎把"执行中断"分成两类处理(worker.ts):

① 租约丢失(优雅中断):任务被用户暂停/取消、或已被别的 worker 接管。此时不记错误,只是把状态改回queued并清空租约——任务毫发无损,随时可以被再次领取。

② 真实执行错误:记录一条error事件,状态置failed并保存错误详情,同时把本次runs记录标记为interrupted/failed。用户可以在界面上直接重试。

③ 进程级重启(最硬的场景):

  • 正在running的任务租约必然过期,下一轮 tick 会被新 worker 重新领取,从最近的 checkpoint 继续;
  • 启动时 recoverInterruptedActions() 会把卡在executing的敏感动作批量标记为outcome_unknown,防止"邮件可能已发出也可能没发出"的歧义被静默吞掉;
  • 每 60 秒一次的 maintain() 维护循环负责"善后对账":补发漏掉的通知、复活被中断的监控任务、修复"已接受但任务未创建"的 Ideas。

这套机制的验收证据记录在 docs/VERIFICATION.md:真实的 PGlite 重启、双 worker 租约竞争、过期租约恢复、暂停/恢复、审批公平性等场景都有自动化测试覆盖。

完整生命周期一图流

创建任务 ──▶ queued(入库) │ worker tick 每秒扫描 │ CAS 抢占成功(写入 leaseId + leaseUntil) ▼ running ──心跳续租(~20s)──▶ checkpoint 存档 ──▶ 完成:succeeded │ │ 租约丢失/被接管 ──▶ 回 queued 等待重领 真实错误 ──▶ failed + 错误事件 │ 进程崩溃 ──▶ 租约过期 ──▶ 下一个 worker 重新领取,从检查点继续

动手阅读源码

  • 存储层与乐观锁:db.ts
  • 租约、心跳与恢复:worker.ts
  • 任务编排与检查点示例:service.ts
  • 任务状态机定义:packages/domain/src/agent.ts
  • 功能总览与验收记录:docs/FEATURES.md、docs/VERIFICATION.md

💡一句话总结:OpenMuse 的"永不丢失"不靠运气,而是靠三条纪律——状态永远在数据库里、写入必须带租约校验、恢复必须从检查点开始。理解了这三点,你就理解了绝大多数可靠任务系统的骨架。

【免费下载链接】openmuseA personal agent with a browser, terminal, files, and work that keeps going built with CopilotKit and AG-UI.项目地址: https://gitcode.com/gh_mirrors/op/openmuse

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 6:02:04

WorkBuddy+微信企业级AI日报自动化架构设计

1. 这不是“发个消息”,而是一套轻量级企业级自动化工作流“我给 WorkBuddy 设了个闹钟:每天上午十点半,一份 AI 日报自动送进微信”——这句话乍看像极了某个程序员朋友在茶水间随口聊起的小技巧,但拆开来看,它其实浓…

作者头像 李华
网站建设 2026/10/1 6:01:56

苹果瑕疵检测数据集:开箱即用的YOLOv5/v8工业质检样本

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 5:58:07

iOS 上运行 Windows 程序:Wine + FEX-Emu + DXMT 兼容层实战

1. 项目缘起:为什么要在 iOS 上折腾 Wine 和 FEX-Emu“Madeira”这个项目名,乍一看像是个地名,但在我们这圈子里,它指的是一套在 iOS 设备上运行 Windows 应用程序的兼容层方案。核心思路是把Wine、FEX-Emu和DXMT这三样东西串起来…

作者头像 李华
网站建设 2026/10/1 5:57:57

微码本质与安全更新:CPU底层补丁技术解析

1. 微码不是“固件”,也不是“驱动”:先划清三道技术边界很多人第一次听到“微码”(microcode)这个词,下意识会把它和BIOS、UEFI固件、CPU驱动甚至主板厂商的管理工具混为一谈。我刚接触这个概念时也犯过同样的错——在…

作者头像 李华
网站建设 2026/10/1 5:57:56

中兴TelnetONU 1.5实战:光猫超级密码与SN认证修改指南

简介:中兴TelnetONU1.5版本是一套面向中兴光猫用户与网络设备管理人员的实用工具包,同时提供Windows与Python两种实现方式,用于开启telnet、修改超级密码及调整SN认证,适合具备一定动手能力的技术爱好者与运维人员。压缩包共23个文…

作者头像 李华