# 2026-06-08 — server_batch 僵尸回收与 stuck 扫描

## 摘要

API 启动时自动收尾因重启遗留的 `running` 批量任务；后台每 60s 扫描 1h 无进展的卡住任务，与脚本执行 `detect_stuck` 对齐。

## 动机

部署重启后任务 #20 等批量作业永久 `running`；MySQL/Redis 与 UI 进度条无法正确结束。

## 涉及文件

- `server/infrastructure/redis/server_batch_store.py` — stuck 阈值、pending 标记、Redis 扫描
- `server/infrastructure/database/server_batch_job_repo.py` — `list_running`
- `server/application/services/server_batch_service.py` — `recover_orphaned_batch_jobs` / `detect_stuck_batch_jobs`
- `server/background/server_batch_reconcile.py` — 60s 周期循环
- `server/main.py` — primary worker 启动回收 + 后台任务
- `tests/test_server_batch_reconcile.py`

## 迁移 / 重启

- 无 DB 迁移
- **需重启 API**（primary worker 启动时执行一次回收）

## 行为

| 场景 | 动作 |
|------|------|
| API 重启时 Redis/MySQL 仍为 `running` | 未完成台 → 失败「服务重启导致任务中断」→ partial/failed |
| 运行中 1h 无 `updated_at` 更新 | 未完成台 → `auto_stuck` → finalize |
| Redis 已过期、MySQL 仍 running | 从 MySQL 重建 live 后回收 |

## 验证

```bash
pytest tests/test_server_batch_reconcile.py -q
bash scripts/local_verify.sh
# 可选：制造 running 任务后 docker restart API，确认任务变为 failed/partial
```
