Files
Nexus/docs/changelog/2026-05-30-heartbeat-422-fix.md
T
Your Name de8d860244 fix: handle legacy agent heartbeat without server_id + migrate on_event to lifespan
- AgentHeartbeat.server_id changed to Optional[int] — missing server_id
  now returns 200 (discarded) instead of 422, stopping retry loops
- web/agent/agent.py: on_event("startup") → FastAPI lifespan pattern
- Added exponential backoff on consecutive heartbeat failures (cap 5min)
- Agent stops heartbeat loop on "discarded" response from central
- main.py: promoted temporary debug 422 handler to production-grade
- uninstall.sh: added legacy agent cleanup (pkill patterns, crontab,
  /opt/multisync-agent path)
- Confirmed servers.html batch buttons work correctly (disabled state
  is correct when no agents installed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 18:20:14 +08:00

1.9 KiB
Raw Blame History

Changelog: 2026-05-30 — Heartbeat 422 修复 + Agent 弃用升级

变更摘要

  1. 修复未注册/旧版 Agent 发送无 server_id 心跳导致 422 日志噪音问题
  2. 将 web/agent/agent.py 的已弃用 on_event("startup") 迁移到 lifespan
  3. Agent 心跳添加指数退避 + discarded 状态自动停止
  4. main.py 临时 RequestValidationError handler 升级为正式版本
  5. 卸载脚本增强对旧版 MultiSync Agent 的清理(crontab/legacy 路径)
  6. 确认 servers.html 批量操作按钮正常工作(disabled 为正确行为)

动机

  • 47.121.118.30 旧版 Agent 持续发无 server_id 心跳,导致 422 日志刷屏
  • 旧 Agent 收到 422 后不断重试,形成噪音循环
  • FastAPI on_event("startup") 已弃用,需迁移到 lifespan
  • Agent 心跳失败无退避,网络抖动时加重服务器负担
  • 卸载脚本未覆盖旧版 MultiSync Agent(非 systemd、非标准路径)

涉及文件

  • server/api/schemas.py — AgentHeartbeat.server_id 改为 Optional[int]
  • server/api/agent.py — heartbeat handler 处理 server_id=None(返回 200 + discarded
  • server/main.py — 移除临时 Debug 注释,正式化 RequestValidationError handler
  • web/agent/agent.py — on_event → lifespan + 指数退避 + discarded 停止
  • web/agent/uninstall.sh — 增加 legacy Agent 进程杀除 + crontab 清理 + 旧路径删除

是否需迁移/重启

  • 需要重启 Nexus 后端(agent.py + schemas.py 变更)
  • 需要重新部署 Agent 脚本到子服务器(下次安装/升级时自动更新)

验证方式

  • python -c "import server.main" 通过
  • ruff check server/api/agent.py server/api/schemas.py server/main.py 通过
  • ast.parse(agent.py) 通过
  • 47.121.118.30 旧 Agent 发心跳 → 返回 200 discarded → 日志 warning 一次,不再循环
  • 新 Agent 心跳失败 → 指数退避(60s → 120s → 240s → 300s cap
  • 新 Agent 收到 discarded → 停止心跳循环 + error 日志