Add job cancellation to the stats dashboard

- Active jobs on /stats get a cancel button wired to the existing
  download/match cancel endpoints, showing "cancelling..." and an inline
  error when the task already finished.
- Cancelling now sets the status immediately, so a task whose runner died
  in a restart stops showing as "downloading".
- Download streams use a bounded read timeout (10 s connect / 60 s read):
  a stalled socket fails within a minute (previously it could block
  forever), and a task cancelled while stalled is marked cancelled rather
  than error.
- The stats job list reaps stale download/match tasks, so phantom jobs
  never appear on the dashboard.
This commit is contained in:
2026-09-17 21:41:54 -05:00
parent b024fc52d7
commit 27cbfd882c
6 changed files with 107 additions and 16 deletions
+8
View File
@@ -122,6 +122,7 @@ def _download_job(task):
"downloaded": task.downloaded,
"total": task.total,
"detail": detail,
"cancelled": task.cancelled,
"created_at": task.created_at,
"updated_at": task.updated_at,
}
@@ -143,6 +144,7 @@ def _match_job(task):
f"{task.processed}/{task.total} · {task.matched} matched · "
f"{task.not_found} not found · {task.deleted} deleted"
),
"cancelled": task.cancelled,
"created_at": task.created_at,
"updated_at": task.updated_at,
}
@@ -150,8 +152,14 @@ def _match_job(task):
def jobs_stats():
"""Running/pending jobs plus the most recently finished ones."""
from apps.library.downloads import reap_stale_downloads
from apps.library.matching import reap_stale_match_tasks
from apps.library.models import DownloadTask, MatchTask
# Tasks whose runner died in a restart must not linger as "downloading".
reap_stale_downloads()
reap_stale_match_tasks()
active_statuses_download = [
DownloadTask.STATUS_PENDING,
DownloadTask.STATUS_DOWNLOADING,