Try the whole ladder, rather than five eighths of it
MAX_ATTEMPTS was 5 while CANDIDATES was 8, so three ranked candidates were gathered and then never tried. The cap was arbitrary and the live numbers show what it cost. slskd answers 500 whenever it cannot open a connection to a peer, and that is common: retrying "Michael Jackson - Billie Jean" walked four unreachable peers before the fifth served it -- succeeding on precisely the last attempt the cap allowed. "The Weeknd - Die For You" ran the same gauntlet and lost, giving up with three untried candidates still on the row. Defaults to CANDIDATES, so the ladder is the ladder. Anyone wanting the old behaviour can still set MUSE_MAX_ATTEMPTS. The cap test lowers the value explicitly now; with the two equal by default it was only ever proving the list ran out, which is the other branch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
baa936e88d
commit
0ebc9515b4
3 files changed
+16
-3
No files matched your search
@@ -561,7 +561,7 @@ stat -c "%h" "/data/media/music/<Artist>/<Album> (<Year>)/<NN> - <Title>.flac"
|
||||
| `MUSE_MIN_MATCH` | `0.45` | filename-to-track similarity floor |
|
||||
| `MUSE_TITLE_FLOOR` | `0.5` | the title alone must clear this before the artist counts |
|
||||
| `MUSE_CANDIDATES` | `8` | ranked candidates kept per request, for fallback |
|
||||
| `MUSE_MAX_ATTEMPTS` | `5` | peers tried before a request is given up on |
|
||||
| `MUSE_MAX_ATTEMPTS` | `MUSE_CANDIDATES` | peers tried before a request is given up on |
|
||||
| `MUSE_ATTEMPT_BACKOFF` | `4` | seconds between candidate attempts |
|
||||
| `MUSE_SYSTEMIC_LIMIT` | `2` | consecutive connection failures before stopping |
|
||||
| `MUSE_STALL_MINUTES` | `20` | a transfer moving no bytes for this long is abandoned |
|
||||
|
||||
@@ -80,7 +80,14 @@ TITLE_FLOOR = float(os.getenv("MUSE_TITLE_FLOOR", "0.5"))
|
||||
# one is tried instead of failing the request -- "File not shared." is a
|
||||
# per-file condition, so candidate two usually just works.
|
||||
CANDIDATES = int(os.getenv("MUSE_CANDIDATES", "8"))
|
||||
MAX_ATTEMPTS = int(os.getenv("MUSE_MAX_ATTEMPTS", "5"))
|
||||
|
||||
# Defaults to the size of the ladder, because keeping eight candidates and then
|
||||
# refusing to try three of them is a cap with no reasoning behind it. Measured
|
||||
# on a live instance: slskd answers 500 whenever it cannot open a connection to
|
||||
# a peer, which is common enough that requests routinely need four or five
|
||||
# attempts. One succeeded on exactly the fifth; another gave up at the cap with
|
||||
# three candidates still in hand.
|
||||
MAX_ATTEMPTS = int(os.getenv("MUSE_MAX_ATTEMPTS", str(CANDIDATES)))
|
||||
|
||||
# A download that has moved no bytes for this long is not going to. The peer
|
||||
# queued it and vanished, or slskd lost the transfer; either way the job used
|
||||
|
||||
@@ -209,12 +209,18 @@ def main() -> int:
|
||||
# every peer refuses to accept the transfer
|
||||
fake2.enqueue_status = {f"u{i}": 500 for i in range(8)}
|
||||
app.slskd_client = fake2
|
||||
# The cap defaults to the ladder size, so lower it here or this only ever
|
||||
# proves the list ran out -- which is a different branch.
|
||||
cap, app.MAX_ATTEMPTS = app.MAX_ATTEMPTS, 3
|
||||
make_job("j2", "Radiohead", "Creep")
|
||||
asyncio.run(app.pick_and_enqueue("j2", "Radiohead", "Creep"))
|
||||
r = job_row("j2")
|
||||
check("gives up at MAX_ATTEMPTS, not at the end of the list",
|
||||
r["state"] == "failed" and r["attempts"] == app.MAX_ATTEMPTS,
|
||||
r["state"] == "failed" and r["attempts"] == 3,
|
||||
f"state={r['state']} attempts={r['attempts']}")
|
||||
check("and leaves the untried remainder alone",
|
||||
len(json.loads(r["candidates"] or "[]")) > 0, r["candidates"])
|
||||
app.MAX_ATTEMPTS = cap
|
||||
check("unreachable peers are reported as such",
|
||||
"could not reach peer" in (r["tried"] or ""), r["detail"])
|
||||
|
||||
|
||||
Reference in new issue
Block a user