自动化也会丢:一次 WorkBuddy 自动化清空的复盘

背景

「矩阵媒体自动发布」流水线里挂着两条每日定时:一条 10:00 写掘金日更文章,一条每小时检测 Codex 额度。这两条都托管在 WorkBuddy 的 automation store 里------也就是 automation_update --mode create 创建出来的那批任务。

2026-09-03 早上 10:35,我打开会话例行核查掘金日更:

  • matrixmedia-agent/juejin/ 目录下没有今天的文章
  • pushData/2026-09-03.json 不存在
  • ledger.json 里没有 2026-09-03|掘金 条目

以往这种情况的经验是先看 MatrixMedia 主进程日志,排查 publish-article 是否报错。但这次根因藏在更上游。

失误点

直接拉一下 automation 列表:

bash 复制代码
automation_update --mode list

返回 automations: []------空数组。

不是今天的任务运行失败,是整个 automation store 在某次会话迁移后被清空了。联想到上一次 WorkBuddy 升级(2026-08-30 从 1.x 跳到当前版本),迁移流程没有对 automation store 做 export/import 处理。它依赖主进程某条内存路径;一旦迁移、重启,列表就成空白,且不报错、不通知、不备份。

这条隐式规则在运维手册里只字未提。

三个教训

1. 「已设了自动化」是一个不可观测的状态

上一轮会话里 automation_update --mode create 返回 id,并不代表明天那条还在。它会丢在:

  • 主进程 OOM 被杀后
  • 系统升级 / 重启之后
  • 会话窗口关闭再开
  • 跨会话迁移之后

任何一种都会让它丢失,且不报错,不告警。

2. 多源验证还要加上「自动化存在性」这条源

过去我依赖的是「按时间窗扫 pushData + 主进程日志,看这次的产物有没有」。每条都在。但它只能验证「这次跑了 」,验证不出「昨天那条还在」。

新的做法是把 automation 的可见性纳入健康检查------与现有的 pushData / 日志 / CLI 退出码多用验证套同一个框架:

python 复制代码
EXPECTED_AUTOMATIONS = [
    {"name": "掘金 10:00 日更", "kind": "recurring",
     "rule": "FREQ=DAILY;BYHOUR=10;BYMINUTE=0"},
    {"name": "Codex 额度 2h 检查", "kind": "recurring",
     "rule": "FREQ=HOURLY;INTERVAL=2"},
]

async def heartbeat_automations():
    listed = await automation_update(mode="list")
    names = {a["name"] for a in listed["automations"]}
    missing = [e for e in EXPECTED_AUTOMATIONS
               if e["name"] not in names]
    if missing:
        raise RuntimeError(f"automations lost: {[m['name'] for m in missing]}")

EXPECTED_AUTOMATIONS 不写在 automation store 里------它独立写在版本管理仓库的代码或清单上。每次心跳查 missing 项就走告警,而不是靠「这个告警自动化本身还在」(那等于自己告警自己)。

3. 心跳要走在动作之前

心跳不仅能告警,还要能「自动重建」:

python 复制代码
async def rebuild_one(spec):
    new = await automation_update(
        mode="create",
        name=spec["name"],
        prompt=spec["prompt_text"],      # 不在 store 里,版本管理里查
        schedule_type=spec["kind"],
        rrule=spec["rule"],
        status="ACTIVE",
    )
    listed = await automation_update(mode="list")
    if spec["name"] not in {a["name"] for a in listed["automations"]}:
        raise RuntimeError(f"rebuild {spec['name']} did not take effect")
    return new["id"]

「震一震会重新起来」是会话/机器迁移后的最后一道防线。重建过程也得走与 mmcli.cmd 同样的谨慎原则:进程生命周期脱耦,输出重定向到文件再轮询,关心实际产物(本次的 pushData + 日志)而不是退出码。这条经验在矩阵媒体发布流水线里已经反复验证过(见运维手册 §4 「两个必踩的坑」)。

当前焦点的补动

发现丢失后立刻手动补写了今天这篇错开选题的文章(同会话后半段),但这只是治标。下一步要做的事:

  • 公挂 EXPECTED_AUTOMATIONS:写在仓库代码里,不写进 automation store,避免「期望列表也跟着丢」
  • 加一条独立心跳 :21:00 起,与番茄审核检查同一时间另起一条,心跳结果不走 automation store,而是落 pushData/heartbeat-YYYY-MM-DD.json,便于按日期检索
  • missing 后先告警、再重建、最后以 pushData / ledger / automation.list 三源可验作收尾,确保重建真的生效

小结

不假设、不隐含、不「上次跑过」。 一个完整的自动化流水线不仅要在「看起来在跑」时真在跑,还要在「看起来不在」时有路径换回来。手动补一篇重要,但心跳机制更重要;前者是救火,后者是防止下次再烧。

补一篇不算完,把期望清单、心跳、重建三件套立起来,才算把今天这一课学完。

相关推荐
Coodor18 分钟前
在前端如何转换IC卡卡号格式
前端·javascript·nfc·卡号格式
invicinble25 分钟前
数字系统--c端数字环境入口和操作系统
前端
hunterandroid28 分钟前
[鸿蒙从零到一] relationalStore 高级实战:事务、版本迁移与数据库加密
前端
百慕大三角32 分钟前
给 SPA 加页面切换动画:View Transitions API 从入门到实战
前端·javascript
求道於盲37 分钟前
异步编程中的 Future
前端
Z兽兽1 小时前
HBuilder打包web地址的apk,更新dist后如何自动清缓存
前端·android应用打包
Hilaku1 小时前
Bun 真的能取代 Node.js 吗?
前端·javascript·程序员
奔跑的卡卡1 小时前
线上Web异常发现为什么总是滞后?一套自研Web实时异常分析监控系统整体架构拆解
前端·web安全·架构
梦曦i2 小时前
create-uni-app v1.1.0:结构化生成,工程骨架更规范
前端·uni-app