Files
Nexus/docs/changelog/2026-06-02-system-bug-fix-7-high.md
T
2026-06-02 01:22:00 +08:00

4.3 KiB
Raw Blame History

2026-06-02 全系统 Bug 扫描与修复

日期

2026-06-02

变更摘要

对全系统进行静态代码扫描,发现并修复 7 个 HIGH 级 Bug


HIGH-1: download_file SSH 连接在流传输前被过早释放

文件: server/api/sync_v2.py

问题: finally 块中 ssh_pool.release()StreamingResponse 生成器尚未开始执行时就关闭连接,导致文件下载中断。

修复: 将 release() 移入 file_generator()finally 子句,在流传输完成或客户端断开后再释放;提前退出(404/400/413)在各自分支 await release()


HIGH-2: WebSocket JWT tv 默认值 -1 与 HTTP 中间件 0 不一致

文件: server/api/websocket.py

问题: _verify_ws_token 对无 tv 字段的旧 token 使用默认值 -1,而数据库 token_versionNULL/0,导致 -1 != 0 判断失败,合法用户 WebSocket 连接被拒。

修复: 对齐 HTTP 中间件逻辑,改为 payload.get("tv") or 0DB 侧 admin.token_version or 0


HIGH-3: retry_runner 达到 max_retries 后任务永久僵尸

文件: server/background/retry_runner.py

问题: 重试次数达到 max_retries 时,任务状态仍维持 pendingretry_count < max_retries 条件不再触发,形成永不被处理的僵尸记录。

修复: 成功/失败分支均检查 retry_count >= max_retries,达到上限时将 status 置为 failed,记录原因日志。


HIGH-4: sync_v2.pysync_engine_v2.py 多处 stderrNone 引发 TypeError

文件: server/api/sync_v2.py, server/application/services/sync_engine_v2.py

问题: 多处直接执行 result["stderr"][:N],当 SSH 执行结果中 stderrNone 时(如连接超时)抛 TypeError: 'NoneType' object is not subscriptable,导致 API 返回 500。

修复: 所有 result["stderr"][:N] 统一改为 (result.get("stderr") or "")[:N],共修复 5 处。


HIGH-5: auth_service._verify_password bcrypt 抛 ValueError 导致 500

文件: server/application/services/auth_service.py

问题: DB 中若存在格式异常的 password_hashbcrypt.checkpw 会抛 ValueError,导致登录接口 500 而非 401。

修复: 用 try/except 包裹 bcrypt.checkpw,异常时返回 False(密码不匹配)。


HIGH-6: install.py /lock 硬编码查询 "admin" 用户名

文件: server/api/install.py

问题: /lock 端点通过 get_by_username("admin") 验证管理员是否创建,若用户在步骤 4 使用了非 admin 的用户名(如 administrator),会错误地拒绝锁定(状态 400),且 DB 不可达时会静默放行锁定操作。

修复: 改为 SELECT COUNT(*) FROM admins WHERE is_active = 1 验证活跃管理员存在;DB 不可达时改为拒绝锁定(503)而非放行。


HIGH-7: heartbeat_flush.py 单条失败污染整批事务

文件: server/background/heartbeat_flush.py

问题: 所有服务器在同一 AsyncSession 中批量更新,单条 UPDATE 失败时仅打日志,但会话处于需要 rollback 的状态,最终 commit() 使整批失败,日志显示 "N 台更新" 实际全部失败。同时修复 datetime 时区感知问题(naive datetime 写入 MySQL)。

修复: 每台服务器使用独立的 AsyncSessionLocal() 上下文,单条失败不影响其他;fromisoformat 后统一补 tzinfo=timezone.utc


涉及文件

文件 修复项
server/api/sync_v2.py HIGH-1(下载连接)、HIGH-4stderr None, 3 处)
server/api/websocket.py HIGH-2WebSocket tv
server/api/install.py HIGH-6/lock 用户名)
server/application/services/auth_service.py HIGH-5bcrypt ValueError
server/application/services/sync_engine_v2.py HIGH-4stderr None, 2 处)
server/background/retry_runner.py HIGH-3(僵尸任务)
server/background/heartbeat_flush.py HIGH-7(事务污染、时区)

需要迁移/重启

  • 后端重启生效(supervisorctl restart nexus
  • 无数据库 migration 变更

验证方式

  1. python -c "import server.main" — 导入无报错 ✓
  2. 登录测试 WebSocket 实时推送
  3. 下载文件功能测试
  4. 查看 push_retry_jobs 表确认无 status=pending 的僵尸记录