Files

4.1 KiB

Queue-Runner / Watchdog 重复审查 Bug(2026-07-02 确诊)

症状

Doro 不断收到同一份合同的重复"审查完毕"通知。同一天内夏阳合同被审查交付2次,家庭医生签约合同被审查交付后又有一个 thread 在跑。

根因

contract-queue-watchdog(cron 3174518affda,每20分钟)与 contract-queue-runner.sh 的交互存在逻辑缺陷:

时间线

  1. Runner 启动,从 manifest.txt 读取待处理文件列表
  2. Runner 对文件A启动 uwf thread start + uwf thread exec --background
  3. 背景 worker(node进程)开始跑 workflow,耗时 1-2 小时
  4. Runner 自身在 wait for worker PID 循环中——但如果 runner 自己因某种原因退出(进程被杀、OOM、超时),只剩 worker 在跑
  5. 关键 bug:workflow 跑完后 deliverer 交付文件 + final_review 通知 Doro,但 runner 已经不在了——无法把文件从 queue/ 移入 done/
  6. 20分钟后 watchdog tick:发现 RUNNER_PID 为空 + DONE_CNT < TOTAL + 无活跃 worker → 重启 runner
  7. 新 runner 读 manifest,发现文件还在 queue/(因为没被移到 done/)→ 再次启动 workflow → 重复审查 → 重复通知

更隐蔽的变体(本次实证)

即使 runner 没死,也会出问题:

  • Runner 在等 worker exit,worker 正常完成 → runner 移文件到 done/ → 进入下一份
  • 但 runner 处理完 manifest 所有文件后正常退出
  • 新文件在 runner 退出后被追加到 manifest(如 auto_notify 追加)
  • Watchdog 重启 runner → runner 从头读 manifest → 前面的文件已在 done/ 会被 SKIP
  • 但如果某份文件在 queue/ 中仍然存在(不在 done/)→ 又跑一遍

为什么文件会在 queue/ 而不在 done/

  1. Runner 异常退出,文件从未被移到 done/
  2. 新追加的文件,上一轮 runner 没跑到就退出了
  3. 文件被 auto_notify 或手动操作重新放回 queue/(不太可能但理论上存在)

缺失的防线

Runner 的 SKIP 逻辑只有一层:

[ -e "$FILE" ] || { log "SKIP (not found / already done): $BASENAME"; continue; }

只看文件是否还在 queue/ 目录。完全不查 contract-tracker.json

修复方案

在 runner 的 === START: 之前加 tracker 查重:

# === BEFORE START: check tracker for already-completed ===
if python3 -c "
import json, sys
t = json.load(open('$HOME/.hermes/data/contract-tracker.json'))
completed = [c['original_filename'] for c in t['contracts'] if c['status']=='completed']
sys.exit(0 if '$BASENAME' in completed else 1)
" 2>/dev/null; then
    log "SKIP (already completed in tracker): $BASENAME"
    mv "$FILE" "$QUEUE_DIR/done/"
    continue
fi

止血操作(已执行)

  1. kill 了正在重复跑的 reviewer thread (06FJ5NPHT9XX63HW0WDKXV3ZSR) 的 worker
  2. kill 了 queue-runner 进程 (PID 1907973)
  3. 将所有已处理文件移入 done/(家庭医生签约、朱家角标识标牌、计划生育协议)
  4. 验证 done/ 数量 ≥ manifest 行数 → watchdog 不会再重启 runner

今天的重复统计

合同 正常审查 重复审查 影响
恭兴 05:00 (end) 02:45被cancel了不算 无重复
肃言 06:25 (end) 无重复
卫健委 07:28 (end) 无重复
夏阳 08:42 (end) 11:40 再跑一遍 (end) ⚠️ 重复通知
家庭医生签约 12:38→19:21交付 19:40又重启→21:16重复交付 ⚠️ 重复通知

Watchdog 今天重启 runner 的次数

今天 watchdog tick 64次,其中触发 runner 重启 41次(00:00-10:40每20分钟都重启一次!)。大多数重启只是空跑(文件都在 done/ 了),但恭兴和夏阳那两次重启时文件还没进 done/,导致重复审查。

相关组件

  • Runner 脚本:~/.hermes/skills/devops/uwf/scripts/contract-queue-runner.sh
  • Watchdog 脚本:~/.hermes/scripts/contract-queue-watchdog.sh
  • Watchdog cron:contract-queue-watchdog (job_id: 3174518affda),每20分钟
  • Queue 目录:/tmp/contract-queue/(manifest.txt + done/)
  • Tracker:~/.hermes/data/contract-tracker.json