Files
hermes-skills/skills/legal/contract-pass-workflow/references/notification-ws-failure-pattern-20260709.md
T

71 lines
2.7 KiB
Markdown

# 交付通知丢失:企微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
### 根因链
1. WeCom WS凌晨不稳定(每30-60min断一次,服务端维护/长连接超时)
2. Gateway自动重连成功但846609持续("not subscribed"是服务端状态滞后)
3. workflow 24/7运行,final_review完成时间不可控
4. 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)增加逻辑:
1. 扫描tracker中 `status=delivered` + `delivered_at > 30min前` + `notification_sent != true`
2.`wecom_dm.py --to doro` 补发通知(独立WS连接)
3. 成功后写 `notification_sent=true` + `notification_at=timestamp`
4. 失败则 `notification_attempts += 1`,下次tick继续重试
5. attempts > 6(即2小时)仍失败→日志告警不再重试
**tracker字段扩展**
```json
{
"notification_sent": false,
"notification_at": null,
"notification_attempts": 0
}
```
**wecom_dm.py优势**
- 独立WS连接,不受gateway状态影响
- 有明确的返回值(success/fail)
- 凌晨WS虽然不稳定但有恢复窗口(如02:04成功发送)
- 20min tick间隔 × 多次重试,大概率能命中一个可用窗口
### 临时止血
当发现合同delivered但Doro没收到通知时:
```bash
python3 ~/.hermes/scripts/wecom_dm.py --to doro --text "合同审查完成通知(补发): ..."
```