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

3.5 KiB

任务队列配置

任务提交后先写入 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 后,在项目根目录执行:

python -B -m unittest discover -s tests -v

队列测试只使用 Python 标准库。接口测试使用 FastAPI TestClient,子进程测试运行短 Python 程序,不加载 YOLO、不发送后端回调。缺少接口测试依赖时会明确显示跳过。