fix(worker): scale slskd download backstop to album size (stop abandoning big albums)
The absolute download backstop was a flat _MAX_XFER_POLLS=1200 (~60min). A large album (e.g. Drake "Scorpion", 521MB / 25 FLACs) from a slow-but-healthy serial peer (~400KB/s, serving one file at a time) needs ~60-70min, so it was cut off at 60min and — because an abandoned transfer is cancelled and re-enqueued from scratch — re-downloaded from zero every attempt, never finishing and eventually going needs_attention at the attempt cap. Replace the flat cap with _max_polls(total_bytes): budget the backstop at a conservative floor throughput (~64KB/s), clamped to [20min, 2h]. Scorpion now gets the full 2h ceiling instead of 60min. The 90s stall timeout is unchanged, so a truly dead/queued peer is still abandoned fast. Follow-up (not in this change): resume across retries (skip files slskd already completed) so an abandoned large download doesn't restart from zero. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,8 +8,12 @@ import pytest
|
||||
import lyra_worker.adapters._slskd as slskd_mod
|
||||
from lyra_worker.adapters._slskd import (
|
||||
_ETA_CAP_SECONDS,
|
||||
_MAX_XFER_POLLS,
|
||||
_MIN_XFER_POLLS,
|
||||
_POLL_SECONDS,
|
||||
SlskdClient,
|
||||
_eta_seconds,
|
||||
_max_polls,
|
||||
_parse_search_responses,
|
||||
)
|
||||
|
||||
@@ -162,6 +166,25 @@ def test_eta_seconds_unknown_cases():
|
||||
assert _eta_seconds(1000, 1000, 100.0) is None # already complete
|
||||
|
||||
|
||||
def test_max_polls_scales_backstop_to_album_size():
|
||||
# A 521MB album (Drake "Scorpion", 25 FLACs) from a slow serial peer must get far more than
|
||||
# the old flat 1200-poll/60min budget, or it gets abandoned mid-download and restarts from zero.
|
||||
scorpion_bytes = 521_000_000
|
||||
polls = _max_polls(scorpion_bytes)
|
||||
assert polls > 1200 # more headroom than the old flat cap
|
||||
assert polls * _POLL_SECONDS >= 90 * 60 # at least ~90 min of wall-clock budget
|
||||
|
||||
# A tiny single stays on the floor, not zero.
|
||||
assert _max_polls(3_000_000) == _MIN_XFER_POLLS
|
||||
assert _max_polls(0) == _MIN_XFER_POLLS
|
||||
|
||||
# An enormous set is clamped to the ceiling (bounds worst-case slot hold).
|
||||
assert _max_polls(50_000_000_000) == _MAX_XFER_POLLS
|
||||
|
||||
# Monotonic: bigger album never gets a smaller budget.
|
||||
assert _max_polls(200_000_000) <= _max_polls(400_000_000)
|
||||
|
||||
|
||||
def test_eta_seconds_capped_when_peer_nearly_stalls():
|
||||
# A near-stalled peer (tiny speed) would yield an ETA far past int4, overflowing the
|
||||
# downloadEtaSeconds column write. The estimate must be clamped to a safe ceiling.
|
||||
|
||||
Reference in New Issue
Block a user