2.7 KiB
2.7 KiB
交付通知丢失:企微WS凌晨断连 + fire-and-forget架构
事件:2026-07-09 职业卫生+舜珙血压计两份合同交付无通知
时间线
- 01:23:06 — 最后一条成功发送(gateway → doro)
- 01:25~01:27 — WS断连(原因未知,WeCom服务端)
- 01:27:23 — 首次846609 "aibot websocket not subscribed"
- 01:28:01 — 职业卫生监督thread=end,final_review尝试通知→失败
- 01:30:44 — WS reconnected
- 02:04:16 — 成功发送(QiuTing),说明短暂恢复
- 02:12:29 — 舜珙thread=end,通知可能在02:05-02:12期间尝试
- 02:15:50 — WS再次断开
- 持续不稳定直到 06:36
根因链
- WeCom WS凌晨不稳定(每30-60min断一次,服务端维护/长连接超时)
- Gateway自动重连成功但846609持续("not subscribed"是服务端状态滞后)
- workflow 24/7运行,final_review完成时间不可控
- final_review通知是fire-and-forget:
_send_wecom(extra, 'doro', msg)调一次,失败即丢弃
通知机制分析
final_review procedure step 3:
cd ~/.hermes/hermes-agent && source venv/bin/activate && python -c "
from tools.send_message_tool import _send_wecom
...asyncio.run(_send_wecom(extra, 'doro', msg))..."
_send_wecom实现:
- 创建新的 WeComAdapter实例
- connect() → send() → disconnect()
- 独立WS连接,不依赖gateway的WS
- 但用的是同一个WeCom API,846609是服务端状态,新连接一样受影响
- 失败返回
{"error": "..."}给LLM,LLM可能仍标记notification_sent=true
7月8日也有相同模式
- 01:13 Timeout → 03:07 reconnect失败 → 06:04 gateway重启才恢复
- 约5小时不可用窗口
解决方案(待实施)
推荐方案B:watchdog补发
- watchdog cron(每20min)增加逻辑:
- 扫描tracker中
status=delivered+delivered_at > 30min前+notification_sent != true - 用
wecom_dm.py --to doro补发通知(独立WS连接) - 成功后写
notification_sent=true+notification_at=timestamp - 失败则
notification_attempts += 1,下次tick继续重试 - attempts > 6(即2小时)仍失败→日志告警不再重试
- 扫描tracker中
tracker字段扩展:
{
"notification_sent": false,
"notification_at": null,
"notification_attempts": 0
}
wecom_dm.py优势:
- 独立WS连接,不受gateway状态影响
- 有明确的返回值(success/fail)
- 凌晨WS虽然不稳定但有恢复窗口(如02:04成功发送)
- 20min tick间隔 × 多次重试,大概率能命中一个可用窗口
临时止血
当发现合同delivered但Doro没收到通知时:
python3 ~/.hermes/scripts/wecom_dm.py --to doro --text "合同审查完成通知(补发): ..."