mirror of
https://github.com/calibrain/shelfmark.git
synced 2026-11-15 13:18:31 +00:00
The torrent stall timer can be deferred for as long as the swarm keeps changing. Since #1494 the torrent handler appends a note to its progress message (`0% · 2 seeds`, and `· 0 seeds, giving up in 7m` while the no-seeders clock runs). `update_download_status` treats any changed message as activity, so a seed count that goes 2, 3, 1 between polls, or the give-up countdown ticking down every minute, refreshes `_last_activity` and the torrent never stalls. A torrent whose seed count stays constant still stalls, which is why this is easy to miss. `shelfmark/download/activity.py` already says what counts: a changed status event or a changed progress value, and a message that changes on a timer proves nothing. So `update_download_status` now compares messages through a small `activity_key()` that drops that trailing seed note. The card still gets every message and shows the live seed count, only the stall clock ignores a change in the note. A new progress percentage, a different client message or a status change still counts as activity. The handler builds the note in `_seed_note` and `activity_key` has to match it, so one test builds the note for a range of seed counts and countdowns and checks the key strips all of them. That also covers the gap #1494 left, where no test connected a handler's message to the orchestrator: the other two drive `update_download_status` with real notes and a fake clock. Without the change the note test fails and the key tests cannot even import `activity_key`. The other orchestrator test is a control that a progress or status change still counts. Full suite passes, and each new test also passes when run alone.
34 lines
1.1 KiB
Python
34 lines
1.1 KiB
Python
"""activity_key drops the swarm note the torrent handler adds beside a progress message."""
|
|
|
|
import pytest
|
|
|
|
from shelfmark.download.activity import activity_key
|
|
|
|
|
|
def _seed_note(seeds, give_up_in):
|
|
# Importing the orchestrator first keeps the handler module out of its import cycle.
|
|
import shelfmark.download.orchestrator # noqa: F401
|
|
from shelfmark.download.clients.base_handler import ExternalClientHandler
|
|
|
|
return ExternalClientHandler._seed_note(seeds, give_up_in)
|
|
|
|
|
|
@pytest.mark.parametrize("seeds", [0, 1, 2, 15, 1200])
|
|
@pytest.mark.parametrize("give_up_in", [None, 0.0, 30.0, 61.0, 3599.0])
|
|
def test_activity_key_strips_whatever_the_handler_appends(seeds, give_up_in):
|
|
message = f"42%{_seed_note(seeds, give_up_in)}"
|
|
|
|
assert activity_key(message) == "42%"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"message",
|
|
["42%", "Fetching metadata", "Seeding (stalled)", "Paused", "No seeders: 0 found, 1 needed"],
|
|
)
|
|
def test_activity_key_leaves_other_messages_alone(message):
|
|
assert activity_key(message) == message
|
|
|
|
|
|
def test_activity_key_keeps_none():
|
|
assert activity_key(None) is None
|