Skip to content

Agent Workflow v0.19.0

Choose a tag to compare

@github-actions github-actions released this 19 Sep 11:55
· 841 commits to main since this release

Agent Workflow v0.19.0

本版本是 v0.18.19 之后的次版本,累计 548 个提交。主线只有一条:数据库 provider 统一抽象(RFC-359)完工。SQLite 与 PostgreSQL 不再是两份各自演化的实现,而是同一份实现跑在两个引擎上。合一过程中照出并修掉了一批「换个数据库结果就不一样」的用户可见缺陷;在 10 万任务规模的真实语料上,PostgreSQL 的三个重端点已经比 SQLite 更快。

本版本有数据库迁移:SQLite 新增 0224–0226(端点 0223 → 0226);PostgreSQL 基线在 v0.18.19 发布后又重采了一次,已经在 v0.18.19 上完成 cutover 的 PostgreSQL 部署需要再重做一次 cutover。从本版本起,PostgreSQL 有了不可变的迁移历史和增量升级链,后续版本可以原地升级。详见文末「升级说明」。

主要更新

数据库 provider 统一抽象完工(RFC-359)

起因是用户的两条要求:「以后不允许再出现两种数据库一个好一个不好的分支」,以及「postgresql 要做到最高性能表现」。v0.18.19 时这项工作还在进行中,本版本 12 条验收标准全部达成。

  • 一份实现:约 150 对按 provider 分开写的孪生适配器,合到只剩 3 对。这 3 对都属于「只有一个引擎才有的资源形态」(SQLite 是一个文件,PostgreSQL 是一台服务器),并且每一对都有两个引擎各跑一遍的对拍测试。数千行 PostgreSQL 副本已经退役。
  • 一条启动序列、一个事务原语:PostgreSQL daemon 与 SQLite 入口按同样的顺序执行同一份启动、恢复与播种逻辑;事务统一走一个中立的异步原语,不再有「同步事务只有 SQLite 能用」的分叉。
  • 验收证据:收口提交的 CI 46 / 46 个作业全绿。其中后端测试在真 PostgreSQL 上跑 23,018 条、在 SQLite 上跑 16,740 条,全部 0 失败。在 10 万任务语料上做 scale=full 性能对比,九个端点全部落在登记值以内,两个引擎返回的数据逐端点一致(itemIds / schemaVersion / nextCursor)。三个重端点 PostgreSQL 显著更快:任务列表首屏的中位数快 77.6ms,运行中任务列表快 37.7ms。
  • 防止分叉重新出现:测试默认用 describeEachProvider 在两个引擎上各跑一遍,缺少 PostgreSQL 连接时直接判失败而不是跳过;孪生适配器数量、裸事务、裸方言等债务都有只降不升的账本守卫。今后新增的功能会自动在两种数据库上接受验证。

合一过程中修掉的「换个数据库结果就不一样」

这些缺陷此前各自的测试都是绿的,直到同一份行为被放到两个引擎上对拍才暴露出来。多数只在 PostgreSQL 上出现:

  • 定时启动:在 PostgreSQL 上,定时启动代理任务或工作组任务会直接返回 HTTP 500。
  • 延后仓库准备(远端暂时拉不动时):SQLite 会留下一行可重试的任务;PostgreSQL 返回 400,而且一行任务都不留。这条落在最主要的启动接口 POST /api/tasks 上。
  • 重试调用节点:在 PostgreSQL 上重试一个「子任务已完成」的调用节点会失败,并让整个任务卡住。
  • 数字员工计划的人工评审闸门:在 PostgreSQL 上永远不会进入 waiting。
  • 取消:PostgreSQL 上的限额取消失效;取消没有读取评审变更号,可能与评审写入交错落库。
  • 同名并发创建:在 PostgreSQL 上返回 500,现已恢复为稳定的 409 冲突。
  • 工作组房间的确认预检:在 PostgreSQL 上是空操作。工作树已经不存在时,SQLite 返回 410,PostgreSQL 却返回 200,随后任务搁浅。
  • 工作流同步:在 PostgreSQL 上会遇到三个问题:血缘写入死锁、内置工作流处理有误,以及预览结果和实际执行的动作不一致。
  • 两个引擎行为不一致、统一取较完整一侧的几处:被取消任务的工作树不回收;工作流被删除后,手动执行在两个引擎上给出不同答案;同步缺少回滚基线的跨行预检;源终止在没有驱动时不同步收尾;恢复管理面两个引擎各有一处弱于对方。
  • 任务列表(这次是 SQLite 出问题):并发的列表查询会合并成一次,但合并键漏掉了「启动来源」筛选。同一时刻按不同来源筛选的两个请求会拿到同一批结果,比如查 api 来源时收到的是定时任务。合并键现在对完整的筛选条件做规范序列化,以后新增筛选项也不会再漏。

性能

  • 认证请求不再每次都写库:此前 PostgreSQL 在每个端点上都比 SQLite 多出 6 条语句,全部来自每次认证请求的两笔记账写。现在 PAT 的 last_used_at 也按会话早已采用的时间窗口合并更新。
  • 单行写入的围栏检查内联:PostgreSQL 单行 INSERT 的 p95 从 18.11ms 降到 4.96ms。
  • 概览与徽标少走往返:概览页的六条资源计数合并成一条 UNION ALL(22 条语句降到 17 条);评审徽标从三次串行往返合并为一次,反问徽标计数也收成一条语句。
  • 新增覆盖索引:分别覆盖概览计数、按仓库查任务和任务列表的分面统计(两个引擎都有)。

其他修复

  • 删除代理的引用检查恢复完整:此前正在运行任务的代理、被定时任务引用的代理都可以被删除,这会导致任务当场失去定义,或定时任务到点后在无人值守时失败;拒绝理由也不会点名是哪项引用挡住了删除。现在五道引用检查全部恢复,拒绝时会列出具体引用。
  • 代理引用了已停用的插件时,保存被拒的报错重新是 plugin-disabled,不再是笼统的 agent-resources-invalid,用户能直接看出要去启用哪个插件。
  • 设置页「按条件批量归档」对非管理员可用:POST /api/tasks/archive 此前对所有非管理员都返回 404,即使对方已被授予 settings:write。
  • git 操作不再被环境变量 GIT_DIR 劫持:GIT_DIR 的优先级高于 git -C,如果 daemon 在设置了 GIT_DIR 的环境里启动,git 操作会不报错地打到另一个仓库。
  • 后端新增常设的「丢 Promise」lint 门禁:门禁上线当天就修掉了 15 处真实丢弃的异步写。这类问题的症状通常是「写入好像没生效」,而且集中出现在崩溃恢复和并发分支上。

升级说明

  • SQLite 新增迁移 0224–0226:0224 退役 node_runs 的血缘补齐触发器,改为在插入时显式写入(这个触发器只存在于 SQLite,是两个引擎分叉的来源之一);0225 / 0226 只新增索引。升级前仍建议备份数据库。
  • PostgreSQL 基线重采(重要):v0.18.19 发布后,基线又重采了一次,补上此前只存在于 SQLite 迁移、没有进入 PostgreSQL 的 schema 保护,例如大小写不敏感的唯一索引,contract digest 因此变化。已经在 v0.18.19 上完成 RFC-349 cutover 的 PostgreSQL 部署,需要再重做一次 cutover。
  • PostgreSQL 从本版本起支持增量升级:迁移历史的根固定为本版本的基线,之后的 schema 变更以追加的升级边(0001、0002 …)原地应用,不再需要重做 cutover。
  • SQLite 写入改为异步执行 + 进程内单写者串行(RFC-359 能力影响 C-2,已确认):事务语义不变,只是并发写请求改为在应用层排队,不再在 SQLite 层 busy-wait。
  • 不要在升级后的数据库上直接回退旧二进制:需要降级时,请停机、换回旧版本,并恢复升级前的备份。

完整变更记录:v0.18.19...v0.19.0