fix: 批量进度只统计无字幕视频,SKIPPED 不计入 total/done

用户反馈数量展示错误:整批 431 个视频中 383 个已有字幕被 SKIPPED,
此前 total=全部视频、done 也含 SKIPPED,把已处理过的视频混进计数。

新口径(2026-09):
- total = 创建时扫描出的无字幕(需处理)视频数,创建即固定;SKIPPED 不计
- done = 实际处理完成(COMPLETED)数,SKIPPED 不计;failed 单独计
- 全部视频都有字幕(total=0)→ 创建即视为 COMPLETED,不排队空跑
- sync_batch_job_progress 同步修正 total(老任务读取时自动收敛到新口径)
- 前端 batchProgress 相应更新:total=0 显示"无待处理视频"

tests: 更新 4 条旧口径断言 + 新增 1 条全跳过 API 测试,62 项相关测试通过。
This commit is contained in:
2026-09-06 17:25:01 +08:00
parent 52512c26e5
commit 44a607b636
5 changed files with 109 additions and 43 deletions
+16 -12
View File
@@ -559,21 +559,25 @@ class Database:
def sync_batch_job_progress(self, job_id: str) -> None:
"""按视频明细实时重算任务的 done/failed 汇总并落库。
"""按视频明细实时对齐任务的 total/done/failed 汇总并落库。
统计口径(2026-09 用户确认):total = 本批**无字幕、需要处理**的视频数
(= 明细里非 SKIPPED 的数量,创建时已固定,运行中 SKIPPED 不会变化);
done = 实际**处理完成**的视频数(仅 COMPLETEDSKIPPED 不计);
failed = 处理失败的视频数。已有字幕直接跳过的视频不参与 total/done。
明细里 COMPLETED 与 SKIPPED 都计入 done(它们都不再需要处理,是任务
已完成的工作量);FAILED 计入 failedPAUSED/PENDING 等状态不计。
引擎在暂停、视频间检查、收尾等边界调用,router 在读取前也调用,保证
前端看到的进度始终与明细一致——即使任务被暂停或进程被终止,汇总字段
也不会停留在创建时的 0(回归 batch_fee668175444处理了 15 个仍显示
前端看到的进度始终与明细一致——即使任务被暂停或进程被终止(回归
batch_fee668175444整批 431 个含 383 个已有字幕,应显示 15/48 而非
0/431)。任务不存在时静默返回。
"""
with self._connect() as conn:
counts = conn.execute(
"""
SELECT
SUM(CASE WHEN status IN ('COMPLETED', 'SKIPPED') THEN 1 ELSE 0 END) AS done,
SUM(CASE WHEN status = 'FAILED' THEN 1 ELSE 0 END) AS failed
SUM(CASE WHEN status = 'COMPLETED' THEN 1 ELSE 0 END) AS done,
SUM(CASE WHEN status = 'FAILED' THEN 1 ELSE 0 END) AS failed,
SUM(CASE WHEN status != 'SKIPPED' THEN 1 ELSE 0 END) AS total
FROM batch_videos WHERE job_id = ?
""",
(job_id,),
@@ -582,16 +586,16 @@ class Database:
# 任务不存在或没有任何明细:无需更新。
return
conn.execute(
"UPDATE batch_jobs SET done = ?, failed = ?, updated_at = ? WHERE id = ?",
(int(counts["done"]), int(counts["failed"]), _now_iso(), job_id),
"UPDATE batch_jobs SET done = ?, failed = ?, total = ?, updated_at = ? WHERE id = ?",
(int(counts["done"]), int(counts["failed"]), int(counts["total"]), _now_iso(), job_id),
)
def refresh_batch_job(self, job_id: str) -> dict[str, Any] | None:
"""实时对齐任务汇总后返回最新记录(读取侧统一入口)。
先 sync_batch_job_progress 让 done/failed 与明细一致,再返回最新 job
任务不存在返回 None。批量引擎与 router 共用此入口,保证各处看到的
进度数字一致。
先 sync_batch_job_progress 让 total/done/failed 与明细一致,再返回
最新 job任务不存在返回 None。批量引擎与 router 共用此入口,保证
各处看到的进度数字一致。
"""
self.sync_batch_job_progress(job_id)
return self.get_batch_job(job_id)