Job 是什么(Agent Job)

一句话总结

Press 给 Agent 下的任务单。每张单子上写了”干什么、在哪台机器上干”,Agent 拿单子执行,干完一笔勾一笔。


🤔 为什么会有它 / 解决了什么问题

Press 需要远程操作多台 VPS:在 f 上建站点、在 n 上更新 nginx、在 f 上构建镜像。每件事一台机器、不同步骤、不能搞混。没有 Job 机制的话,Press 只能 SSH 进去手动敲命令,跟同时管十台机器的运维一样乱。

Job 把每个操作包装成可追踪的任务单:Press 发布 → Agent 领取 → 逐步骤执行 → 每步汇报状态 → 最终成功或失败。Press 不需要知道 Agent 在执行什么,只要看 Job 状态就知道进度。


🔍 具体原理 / 运作逻辑

  1. 你在 Press UI 做操作(如”创建站点”)→ Press 后端创建一条 Agent Job 记录,状态 Pending
  2. Agent 通过 WebSocket 拉取分配给自己的 Job
  3. Agent 执行 Job 里的每个 step(如:建数据库 → 装 frappe → 配 nginx)
  4. 每个 step 完成后 Agent 向 Press 汇报状态
  5. 全部 step 成功 → Job 状态变为 Success → Press 更新相关记录(如 Site → Active)

Job 的状态机

Pending → Running → Success
                  → Failure → Undelivered(投递失败)

🧭 什么情况下会用到 / 什么场景会遇到它

  • 创建站点 → New Site Job + Add Site to Upstream Job
  • 部署 Bench → New Bench Job
  • Build 镜像 → Build Job
  • 更新 nginx → Reload Nginx Job
  • 排查问题 → 看 Job 状态判断卡在哪一步

⚖️ 副作用 / 代价 / 取舍

  • Undelivered 堆积:某些 Job Type 失败后不重试,永远卡住。不影响核心功能但数据库里留脏数据
  • 状态更新滞后:Agent 执行完了但最后一步缺 @step 装饰器 → Job 永远 Running → Site 永远 Installing(实际已正常)
  • Job 失败不报错Agent Job 失败后 Press 只是设 creation_failed 时间戳,不在 UI 上弹明显的错误提示
  • 手动改 Job 状态是红线frappe.db.set_value('[[Job|Agent Job]]', 'xxx', 'status', 'Success') 违反了 CLAUDE.md 禁止事项

🕰️ 来历

  • Frappe Cloud 团队的内部任务调度机制
  • frappe/agent 配套设计:Press 发 Job,Agent 跑 Job
  • 我们用的是同一套机制,没有改动

🔗 关联 / 经常一起出现的概念

  • Agent:Job 的执行者。Press 发 Job,Agent 领 Job、跑 Job
  • Press:Job 的发布者。所有 Job 由 Press 创建和管理
  • @step 装饰器:标记 Agent 执行 Job 时的一个步骤。缺了 → 步骤执行了但状态不更新
  • Undelivered:Job 的失败状态。Agent 没收到或拒绝执行
  • creation_failed:Site 表的字段。New Site Job 失败时 Press 写入,14 天后自动下架

⚠️ 注意事项 / 常见误区

  • Job 是 Press 推送给 Agent 的(不是 Agent 主动查),走的是 Agent 到 Press 的 WebSocket 长连接
  • “Job 状态 Success” 不等于实际执行正确——如果 Agent 源码有 bug(如缺 @step),实际执行了但状态没更新
  • n+f 合并架构下,Add Site to Upstream Job 默认分配给 n1。如果 Agent 只注册为 f1,这个 Job 永远 Undelivered

🕳️ 踩坑案例

当时的现象:gottenergy 站点迁移后 Press UI 显示 Broken,红色警告”网站创建失败了,14天后自动下架”。

排查过程:查 Site → creation_failed 有时间戳 → 追踪到 Agent Job “New Site” 状态 Failure → 因为站点是手动迁移的,Agent 没法在已有机器上”创建”一个已存在的站点

最后发现site.insert() 时 Press 自动创建了 Agent Job,但站点数据是手动恢复的,Agent 执行必然失败

这件事之后我记住了什么:手动迁移的站点需要清理 Agent Job 状态,不能走正常流程。全新部署不走这条路。


📎 记忆锚点

Job = 快递单号。Press 发货(创建 Job),Agent 送货(执行 Job),每一步扫码更新物流状态(step 汇报)。单号追踪全程。


📝 更新日志

日期改动原因
2026-07-08首次创建名词科普