Files
pifu/TASK_QUEUE.md
T
2026-09-11 13:41:40 +08:00

61 lines
3.5 KiB
Markdown

# 任务队列配置
任务提交后先写入 SQLite,再由固定数量的工作线程分发给常驻分析子进程。
服务启动时每个子进程加载一次 YOLO,并使用 640×640 空白图片预热;全部就绪后 API 才开放。
后续任务复用同一模型。YOLO 推理通过模型独占锁串行执行,其他图片分析仍可并行。
原有提交、查询和列表接口路径不变,重复提交等待中或运行中的任务不会重复执行。
| 环境变量 | 默认值 | 说明 |
| --- | --- | --- |
| `MAX_CONCURRENT_TASKS` | `1` | 同时运行的分析子进程数,必须大于 0 |
| `MAX_PENDING_TASKS` | `100` | 等待队列容量,不含运行中的任务,必须大于 0 |
| `TASK_DB_PATH` | 项目下 `data/tasks.sqlite3` | SQLite 文件路径 |
| `MODEL_PATH` | 项目下 `best.pt` | 模型路径,Compose 使用 `/app/best.pt` |
| `IMAGE_WORKERS` | `4` | 每个任务的图片处理线程数 |
每增加一个任务并发槽位都会常驻一份模型,占用额外内存或显存。
启动预热超时为 180 秒,每个任务超时为 3600 秒。超时、崩溃或停止会回收对应进程;
下一个任务重新创建并预热该槽位,不自动重试已经失败的任务。
Compose 将数据库放在 `/data/analysis/.worker/tasks.sqlite3`,由现有的
`/data/analysis:/data/analysis` 挂载持久保存。目录必须可写,数据库应放在本机磁盘,
不要放到网络共享文件系统。修改配置后重启服务生效。
队列满时,新任务返回 HTTP 429 和 `Retry-After: 5`;已有活动任务仍正常返回状态。
`/health` 增加 `tasks.pending` 和 `queue` 配置字段。
## 重启与停止
- 已完成和失败的任务保留,可以继续查询。
- `pending` 任务重启后继续执行;输入目录在提交时解析并保存,跨天不会重新选日期。
- 异常退出留下的 `running` 任务启动时标记为 `failed`,错误提示重新提交。
- 正常停止会终止、回收正在执行的分析子进程,并将对应任务标记失败;等待任务保留。
- 不自动重试中断任务,避免重复生成结果或重复回调。
使用单个 API worker 和单个服务实例。独占锁会拒绝第二个进程同时打开同一队列,
避免并发上限被成倍放大。不同数据库之间不共享限制。
如果只强制杀死 API 父进程,操作系统可能留下分析子进程;再次启动前需要确认这些进程已结束。
容器部署应停止/重启整个容器。
## 回调与范围
回调仅记录已知运行任务的结果,任务仍保持 `running`,直到常驻进程返回该任务的结果。
失败回调不会被成功结果覆盖;未知任务返回 404;等待中和已结束任务不接受状态覆盖。
外部回调载荷仍为 `task_id` 和 `status`。
图片算法、输出目录规则和报告格式保持原样。空目录、部分分析失败、报告写入失败会明确返回失败,
避免把不完整处理当成测速成功。回调仍同步执行,没有加入独立通知队列。
现有输出目录可能发生覆盖,调整并发数前应先处理任务输出隔离。
历史内存字典无法在重启后迁移;持久化从此版本接收的任务开始。
## 验证
安装服务依赖和 `httpx` 后,在项目根目录执行:
```text
python -B -m unittest discover -s tests -v
```
队列测试只使用 Python 标准库。接口测试使用 FastAPI TestClient,子进程测试运行短 Python
程序,不加载 YOLO、不发送后端回调。缺少接口测试依赖时会明确显示跳过。