Fix download cleanup after wishlist runs
- ignore unconfigured backends when clearing completed downloads - keep the post-download cleanup route best-effort after a successful wishlist run - add regression coverage for the orchestrator clear step
This commit is contained in:
parent
a7c1bb96a1
commit
f75c180cb6
3 changed files with 81 additions and 6 deletions
|
|
@ -457,12 +457,25 @@ class DownloadOrchestrator:
|
|||
True if successful
|
||||
"""
|
||||
results = []
|
||||
for client in [self.soulseek, self.youtube, self.tidal, self.qobuz, self.hifi, self.deezer_dl, self.lidarr]:
|
||||
if client:
|
||||
try:
|
||||
results.append(await client.clear_all_completed_downloads())
|
||||
except Exception:
|
||||
pass
|
||||
for name, client in [
|
||||
("soulseek", self.soulseek),
|
||||
("youtube", self.youtube),
|
||||
("tidal", self.tidal),
|
||||
("qobuz", self.qobuz),
|
||||
("hifi", self.hifi),
|
||||
("deezer_dl", self.deezer_dl),
|
||||
("lidarr", self.lidarr),
|
||||
]:
|
||||
if not client:
|
||||
continue
|
||||
if hasattr(client, "is_configured") and not client.is_configured():
|
||||
logger.debug("Skipping %s clear_all_completed_downloads (not configured)", name)
|
||||
continue
|
||||
try:
|
||||
results.append(await client.clear_all_completed_downloads())
|
||||
except Exception as exc:
|
||||
logger.warning("%s clear_all_completed_downloads failed: %s", name, exc)
|
||||
results.append(False)
|
||||
|
||||
return all(results) if results else True
|
||||
|
||||
|
|
|
|||
61
tests/downloads/test_download_orchestrator.py
Normal file
61
tests/downloads/test_download_orchestrator.py
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
from core.download_orchestrator import DownloadOrchestrator
|
||||
|
||||
|
||||
class _FakeClient:
|
||||
def __init__(self, configured=True, clear_result=True):
|
||||
self.configured = configured
|
||||
self.clear_result = clear_result
|
||||
self.clear_calls = 0
|
||||
|
||||
def is_configured(self):
|
||||
return self.configured
|
||||
|
||||
async def clear_all_completed_downloads(self):
|
||||
self.clear_calls += 1
|
||||
return self.clear_result
|
||||
|
||||
|
||||
def _build_orchestrator(**clients):
|
||||
orch = DownloadOrchestrator.__new__(DownloadOrchestrator)
|
||||
orch.soulseek = clients.get("soulseek")
|
||||
orch.youtube = clients.get("youtube")
|
||||
orch.tidal = clients.get("tidal")
|
||||
orch.qobuz = clients.get("qobuz")
|
||||
orch.hifi = clients.get("hifi")
|
||||
orch.deezer_dl = clients.get("deezer_dl")
|
||||
orch.lidarr = clients.get("lidarr")
|
||||
return orch
|
||||
|
||||
|
||||
def _run_async(coro):
|
||||
import asyncio
|
||||
|
||||
loop = asyncio.new_event_loop()
|
||||
try:
|
||||
return loop.run_until_complete(coro)
|
||||
finally:
|
||||
loop.close()
|
||||
|
||||
|
||||
def test_clear_all_completed_downloads_ignores_unconfigured_clients():
|
||||
orch = _build_orchestrator(
|
||||
soulseek=_FakeClient(configured=True, clear_result=True),
|
||||
youtube=_FakeClient(configured=False, clear_result=False),
|
||||
)
|
||||
|
||||
result = _run_async(orch.clear_all_completed_downloads())
|
||||
|
||||
assert result is True
|
||||
assert orch.soulseek.clear_calls == 1
|
||||
assert orch.youtube.clear_calls == 0
|
||||
|
||||
|
||||
def test_clear_all_completed_downloads_propagates_configured_failures():
|
||||
orch = _build_orchestrator(
|
||||
soulseek=_FakeClient(configured=True, clear_result=False),
|
||||
)
|
||||
|
||||
result = _run_async(orch.clear_all_completed_downloads())
|
||||
|
||||
assert result is False
|
||||
assert orch.soulseek.clear_calls == 1
|
||||
|
|
@ -20583,6 +20583,7 @@ def _build_master_deps():
|
|||
)
|
||||
|
||||
|
||||
|
||||
def _run_full_missing_tracks_process(batch_id, playlist_id, tracks_json):
|
||||
return _downloads_master.run_full_missing_tracks_process(
|
||||
batch_id, playlist_id, tracks_json, _build_master_deps()
|
||||
|
|
|
|||
Loading…
Reference in a new issue