fix(download): stop stale aria2 GIDs from spamming errors after queue clears

- Log expected "GID not found" tellStatus probes at DEBUG, and treat a
  forgotten GID as permanent so the poll loop recovers immediately
  instead of burning 4 retries x 3s of ERROR lines per cycle
- cancel_download tolerates a forgotten GID and always pops the
  in-memory transfer so concurrent polls cannot re-register a
  cancelled download
- Restore sweep deletes aria2 state records with no resolvable target
  path instead of skipping them forever
- Clearing the download queue now also cancels in-memory tasks, removes
  live aria2 transfers and drops persisted state for the cleared ids
  (partial files on disk are preserved)
This commit is contained in:
Will Miao
2026-08-25 08:19:54 +08:00
parent da071e8452
commit 41ed03e5c6
8 changed files with 390 additions and 28 deletions
@@ -495,3 +495,29 @@ async def test_dedup_history_collapses_same_file_and_legacy_rows(tmp_path: Path)
history = await svc.get_history()
remaining = {item["download_id"] for item in history["items"]}
assert remaining == {"dl-x2", "dl-y2"}
# ---------------------------------------------------------------------------
# clear_queue
# ---------------------------------------------------------------------------
@pytest.mark.asyncio
async def test_clear_queue_returns_deleted_ids(tmp_path: Path) -> None:
"""clear_queue reports the download_ids it removed so callers can tear
down any in-memory tracking for them."""
svc = _make_service(tmp_path)
await svc.add_to_queue(download_id="dl-1", model_id=1)
await svc.add_to_queue(download_id="dl-2", model_id=2)
await svc.add_to_queue(download_id="dl-3", model_id=3)
await svc.update_status("dl-3", "downloading")
cleared = await svc.clear_queue(status_filter="queued")
assert sorted(cleared) == ["dl-1", "dl-2"]
remaining = await svc.get_queue()
assert [row["download_id"] for row in remaining] == ["dl-3"]
cleared_all = await svc.clear_queue()
assert cleared_all == ["dl-3"]
assert await svc.get_queue() == []