smart queue fix

This commit is contained in:
Mateusz Gruszczyński
2026-05-05 15:43:56 +02:00
parent 912d89abba
commit 0e0c3359ee

View File

@@ -369,15 +369,15 @@ def _cleanup_auto_labels(client: Any, profile_id: int, torrents: list[dict[str,
def _is_running_download_slot(t: dict[str, Any]) -> bool:
"""Return True for incomplete torrents that already occupy a Smart Queue slot."""
# Note: Limit Smart Queue oznacza docelową liczbę slotów włączonych do pobierania.
# rTorrent często pokazuje d.is_active=0 dla torrentów bez chwilowego transferu, więc slot liczymy
# po d.state=1. Techniczny label Smart Queue jest wyjątkiem: oznacza pozycję oczekującą/pauzowaną,
# której nie wolno liczyć jako aktywnej. Dzięki temu przy limicie 100 i 82 slotach dobieramy 18.
# Note: Limit Smart Queue oznacza docelową liczbę realnie uruchomionych slotów.
# rTorrent potrafi trzymać paused jako state=1, dlatego slot liczymy po state=1 tylko wtedy,
# gdy torrent nie ma statusu Paused i nie jest oznaczony technicznym labelem Smart Queue.
if int(t.get('complete') or 0):
return False
if str(t.get('label') or '') == SMART_QUEUE_LABEL:
return False
if str(t.get('status') or '').lower() == 'checking':
status = str(t.get('status') or '').lower()
if status == 'checking' or status == 'paused' or bool(t.get('paused')):
return False
return bool(int(t.get('state') or 0))
@@ -484,9 +484,9 @@ def check(profile: dict | None = None, user_id: int | None = None, force: bool =
to_pause: list[dict[str, Any]] = pause_rank[:max(0, len(downloading) - max_active)]
pause_hashes = {str(t.get('hash') or '') for t in to_pause}
# When the cap is not exceeded, stalled downloads can still be rotated out
# one-for-one with better stopped candidates while staying within max_active.
if candidates:
# Note: Rotacja stalled działa tylko przy pełnej kolejce. Gdy brakuje slotów, Smart Queue ma
# najpierw dobrać brakujące pozycje, a nie pauzować już istniejące lub błędnie uznane za stalled.
if candidates and len(downloading) >= max_active:
replaceable_stalled = [t for t in stalled if str(t.get('hash') or '') not in pause_hashes]
for t in replaceable_stalled[:max(0, len(candidates) - len(to_pause))]:
to_pause.append(t)
@@ -547,6 +547,6 @@ def check(profile: dict | None = None, user_id: int | None = None, force: bool =
| {str(t.get('hash') or '') for t in stopped if str(t.get('label') or '') == SMART_QUEUE_LABEL and str(t.get('hash') or '') not in set(resumed)}
)
restored = _cleanup_auto_labels(c, profile_id, torrents, keep_labels, manage_stopped)
details = {'excluded': len(excluded), 'enabled': bool(settings.get('enabled')), 'auto_label': SMART_QUEUE_LABEL, 'labels_restored': restored, 'labels_failed': label_failed, 'start_failed': start_failed, 'start_no_effect': start_no_effect, 'resume_requested': resume_requested, 'active_verified': active_verified, 'waiting_labeled': len(to_label_waiting), 'manage_stopped': manage_stopped, 'max_active_downloads': max_active, 'active_before': len(downloading), 'active_after': active_after_pause + len(resumed), 'rtorrent_cap': rtorrent_cap}
details = {'excluded': len(excluded), 'enabled': bool(settings.get('enabled')), 'auto_label': SMART_QUEUE_LABEL, 'labels_restored': restored, 'labels_failed': label_failed, 'start_failed': start_failed, 'start_no_effect': start_no_effect, 'resume_requested': resume_requested, 'active_verified': active_verified, 'waiting_labeled': len(to_label_waiting), 'manage_stopped': manage_stopped, 'max_active_downloads': max_active, 'active_before': len(downloading), 'active_after_expected': active_after_pause + len(resumed), 'paused_planned': len(to_pause), 'resumed_planned': len(to_resume), 'rtorrent_cap': rtorrent_cap}
add_history(profile_id, 'force_check' if force else 'auto_check', paused, resumed, len(torrents), details, user_id)
return {'ok': True, 'enabled': bool(settings.get('enabled')), 'paused': paused, 'resumed': resumed, 'resume_requested': resume_requested, 'waiting_labeled': len(to_label_waiting), 'labels_restored': restored, 'labels_failed': label_failed, 'start_failed': start_failed, 'start_no_effect': start_no_effect, 'active_verified': active_verified, 'rtorrent_cap': rtorrent_cap, 'checked': len(torrents), 'excluded': len(excluded), 'settings': settings}