Fix: Prowlarr seedtime priority (#946)

This commit is contained in:
Alex
2026-05-04 14:25:05 +01:00
committed by GitHub
parent ba62771a53
commit 196578fb18
7 changed files with 262 additions and 11 deletions
@@ -156,6 +156,43 @@ def test_queue_release_persists_generic_retry_resolution_fields(monkeypatch):
assert task.can_retry_without_staged_source is True
def test_queue_release_prefers_configured_seed_time_minutes_for_retry(monkeypatch):
import shelfmark.download.orchestrator as orchestrator
captured: dict[str, object] = {}
def fake_add(task):
captured["task"] = task
return True
monkeypatch.setattr(orchestrator.book_queue, "add", fake_add)
monkeypatch.setattr(orchestrator, "ws_manager", None)
success, error = orchestrator.queue_release(
{
"source": "prowlarr",
"source_id": "prowlarr-release-configured-seed-time",
"title": "Queued Prowlarr Release",
"download_url": "magnet:?xt=urn:btih:abc123",
"protocol": "torrent",
"extra": {
"configured_ratio_limit": 2,
"configured_seed_time_minutes": 7200,
"minimum_ratio": 1,
"minimum_seed_time": 259200,
},
},
user_id=42,
username="alice",
)
assert success is True
assert error is None
task = captured["task"]
assert task.retry_ratio_limit == 2.0
assert task.retry_seeding_time_limit_minutes == 7200
def test_queue_release_returns_error_for_operational_queue_failure(monkeypatch):
import shelfmark.download.orchestrator as orchestrator
+26
View File
@@ -260,6 +260,32 @@ class TestProwlarrHandlerSeedCriteria:
assert request.seeding_time_limit == 4320
assert request.ratio_limit == 1.0
def test_resolve_download_prefers_configured_seed_time_minutes(self):
with patch(
"shelfmark.release_sources.prowlarr.handler.get_release",
return_value={
"protocol": "torrent",
"title": "Test Release",
"magnetUrl": "magnet:?xt=urn:btih:abc123",
"configuredSeedTimeMinutes": 7200,
"configuredRatioLimit": 2,
"minimumSeedTime": 259200,
"minimumRatio": 1,
},
):
handler = ProwlarrHandler()
task = DownloadTask(
task_id="configured-seed-time",
source="prowlarr",
title="Test Book",
)
request = handler._resolve_download(task, lambda *_: None)
assert request is not None
assert request.seeding_time_limit == 7200
assert request.ratio_limit == 2.0
def test_resolve_download_rounds_seed_time_up_to_next_minute(self):
with patch(
"shelfmark.release_sources.prowlarr.handler.get_release",
+87 -2
View File
@@ -6,6 +6,7 @@ Tests the utility functions for parsing release metadata.
# Import the functions to test
from shelfmark.metadata_providers import BookMetadata
from shelfmark.release_sources.prowlarr.api import ProwlarrClient
from shelfmark.release_sources.prowlarr.source import (
ProwlarrSource,
_detect_content_type_from_categories,
@@ -210,9 +211,11 @@ class TestDetectContentType:
class FakeTorznabClient:
def __init__(self):
def __init__(self, search_results=None, seed_settings=None):
self.calls: list[tuple[str, object]] = []
self.queries: list[str] = []
self.search_results = search_results or []
self.seed_settings = seed_settings or {}
def get_enabled_indexers_detailed(self):
return [
@@ -241,12 +244,47 @@ class FakeTorznabClient:
del indexer_id, search_type, limit, offset
self.calls.append((query, categories))
self.queries.append(query)
return []
return self.search_results
def get_enriched_indexer_ids(self, restrict_to=None):
del restrict_to
return []
def get_indexer_seed_settings(self, restrict_to=None):
del restrict_to
return self.seed_settings
class TestProwlarrIndexerSeedSettings:
def test_get_indexer_seed_settings_reads_prowlarr_minutes_field(self, monkeypatch):
client = ProwlarrClient("http://prowlarr:9696", "apikey")
monkeypatch.setattr(
client,
"get_enabled_indexers_detailed",
lambda: [
{
"id": 13,
"protocol": "torrent",
"fields": [
{"name": "torrentBaseSettings.seedRatio", "value": "2.5"},
{"name": "torrentBaseSettings.seedTime", "value": "7200"},
],
},
{
"id": 14,
"protocol": "usenet",
"fields": [
{"name": "torrentBaseSettings.seedRatio", "value": "3"},
{"name": "torrentBaseSettings.seedTime", "value": "9999"},
],
},
],
)
assert client.get_indexer_seed_settings() == {
13: {"ratio_limit": 2.5, "seeding_time_limit_minutes": 7200}
}
class TestProwlarrLocalizedQueries:
def test_manual_query_still_applies_content_type_categories(self, monkeypatch):
@@ -309,6 +347,53 @@ class TestProwlarrLocalizedQueries:
assert fake_client.calls == [("my custom", None)]
def test_search_attaches_configured_seed_time_minutes_to_release(self, monkeypatch):
import shelfmark.release_sources.prowlarr.source as prowlarr_source
def fake_get(key: str, default=None):
values = {
"PROWLARR_INDEXERS": "",
"PROWLARR_AUTO_EXPAND": False,
}
return values.get(key, default)
monkeypatch.setattr(prowlarr_source.config, "get", fake_get)
fake_client = FakeTorznabClient(
search_results=[
{
"guid": "mam-result-1",
"protocol": "torrent",
"title": "Test Release",
"magnetUrl": "magnet:?xt=urn:btih:abc123",
"indexerId": 1,
"indexer": "MyAnonamouse",
"minimumSeedTime": 259200,
"minimumRatio": 1,
}
],
seed_settings={1: {"ratio_limit": 2.0, "seeding_time_limit_minutes": 7200}},
)
source = ProwlarrSource()
monkeypatch.setattr(source, "_get_client", lambda: fake_client)
book = BookMetadata(
provider="hardcover",
provider_id="123",
title="Anything",
authors=["Someone"],
)
from shelfmark.core.search_plan import build_release_search_plan
plan = build_release_search_plan(book, languages=["en"])
releases = source.search(book, plan, content_type="ebook")
assert len(releases) == 1
assert releases[0].extra["configured_ratio_limit"] == 2.0
assert releases[0].extra["configured_seed_time_minutes"] == 7200
assert releases[0].extra["minimum_seed_time"] == 259200
def test_search_uses_localized_titles_when_available(self, monkeypatch):
import shelfmark.release_sources.prowlarr.source as prowlarr_source