fix(worker): cancel abandoned slskd transfers + cap download fall-through
Two compounding causes of 'many downloads of one album from different sources' in slskd: (1) the slskd client raised on timeout/error WITHOUT cancelling the transfer it enqueued, so as the pipeline fell through to other peers each left a transfer running; (2) the incomplete-download fall-through was uncapped, grinding through every candidate of a popular album (~200 Soulseek peers), amplified now that Qobuz pacing pushes most jobs to Soulseek. - SlskdClient.download now cancels its enqueued transfers (DELETE) on any abandon. - The download loop caps at _MAX_DOWNLOAD_ATTEMPTS (6) candidates. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -89,3 +89,37 @@ def test_all_sources_incomplete_still_needs_attention(conn, tmp_path):
|
||||
run_pipeline(conn, job_id, [_Qobuz(deliver=2), _Soulseek(deliver=1)], dest_root=str(tmp_path))
|
||||
assert _state_error(conn, job_id) == ("needs_attention", "incomplete download")
|
||||
assert not (tmp_path / "Radiohead" / "In Rainbows").exists() # nothing imported
|
||||
|
||||
|
||||
class _CountingIncompleteQobuz:
|
||||
"""Offers `n` candidates that all download but come back incomplete; counts download calls."""
|
||||
name = "qobuz"
|
||||
tier = 0
|
||||
|
||||
def __init__(self, n):
|
||||
self.n = n
|
||||
self.calls = 0
|
||||
|
||||
def health(self):
|
||||
return True
|
||||
|
||||
def search(self, target):
|
||||
q = _HIRES
|
||||
return [Candidate(source="qobuz", source_ref=f"r{i}", matched_artist=target.artist,
|
||||
matched_album=target.album, quality=q, track_count=3, source_tier=0)
|
||||
for i in range(self.n)]
|
||||
|
||||
def download(self, candidate, dest, on_progress):
|
||||
self.calls += 1
|
||||
_stage(dest, 1) # 1 of 3 → always incomplete
|
||||
return DownloadResult(ok=True, path=dest, track_count=1)
|
||||
|
||||
|
||||
def test_fall_through_is_capped(conn):
|
||||
from lyra_worker.pipeline import _MAX_DOWNLOAD_ATTEMPTS
|
||||
a = _CountingIncompleteQobuz(n=20)
|
||||
job_id = insert_request(conn, artist="Radiohead", album="In Rainbows")
|
||||
claim_next(conn)
|
||||
run_pipeline(conn, job_id, [a], dest_root="/tmp/lib-cap")
|
||||
assert _state_error(conn, job_id) == ("needs_attention", "incomplete download")
|
||||
assert a.calls == _MAX_DOWNLOAD_ATTEMPTS # capped, not all 20 peers tried
|
||||
|
||||
Reference in New Issue
Block a user