smart queue fix

This commit is contained in:
Mateusz Gruszczyński
2026-05-05 09:53:14 +02:00
parent 3c14a6f510
commit 08772ddda5

View File

@@ -165,7 +165,7 @@ def _restore_auto_label(client: Any, profile_id: int, torrent_hash: str, current
previous = row.get('previous_label') or '' previous = row.get('previous_label') or ''
live_label = _read_label(client, torrent_hash, current_label or '') live_label = _read_label(client, torrent_hash, current_label or '')
try: try:
# Note: Before Smart Queue resumes a paused torrent, restore the user label only when the auto label is still present. # Note: Przy wznowieniu Smart Queue oddaje poprzedni label tylko wtedy, gdy nadal widzi swój label techniczny.
if live_label == SMART_QUEUE_LABEL or current_label is None: if live_label == SMART_QUEUE_LABEL or current_label is None:
client.call('d.custom1.set', torrent_hash, previous) client.call('d.custom1.set', torrent_hash, previous)
conn.execute('DELETE FROM smart_queue_auto_labels WHERE profile_id=? AND torrent_hash=?', (profile_id, torrent_hash)) conn.execute('DELETE FROM smart_queue_auto_labels WHERE profile_id=? AND torrent_hash=?', (profile_id, torrent_hash))
@@ -195,27 +195,47 @@ def _mark_auto_paused(client: Any, profile_id: int, torrent: dict[str, Any]) ->
return _set_smart_queue_label(client, torrent_hash) return _set_smart_queue_label(client, torrent_hash)
def _is_smart_queue_hold(torrent: dict[str, Any] | None) -> bool:
if not torrent or int(torrent.get('complete') or 0):
return False
return bool(torrent.get('paused')) or not int(torrent.get('active') or 0) or not int(torrent.get('state') or 0)
def _clear_untracked_smart_queue_label(client: Any, torrent_hash: str, current_label: str) -> bool:
if current_label != SMART_QUEUE_LABEL:
return False
try:
# Note: Czyści osierocony label Smart Queue, gdy brak wpisu z poprzednim labelem w bazie.
client.call('d.custom1.set', torrent_hash, '')
return True
except Exception:
return False
def _cleanup_auto_labels(client: Any, profile_id: int, torrents: list[dict[str, Any]], keep_hashes: set[str]) -> list[str]: def _cleanup_auto_labels(client: Any, profile_id: int, torrents: list[dict[str, Any]], keep_hashes: set[str]) -> list[str]:
by_hash = {str(t.get('hash') or ''): t for t in torrents} by_hash = {str(t.get('hash') or ''): t for t in torrents}
restored: list[str] = [] restored: list[str] = []
with connect() as conn: with connect() as conn:
rows = conn.execute('SELECT torrent_hash FROM smart_queue_auto_labels WHERE profile_id=?', (profile_id,)).fetchall() rows = conn.execute('SELECT torrent_hash FROM smart_queue_auto_labels WHERE profile_id=?', (profile_id,)).fetchall()
tracked_hashes = {str(row.get('torrent_hash') or '') for row in rows if row.get('torrent_hash')}
for row in rows: for row in rows:
h = str(row.get('torrent_hash') or '') h = str(row.get('torrent_hash') or '')
t = by_hash.get(h) t = by_hash.get(h)
if not h or h in keep_hashes: if not h or h in keep_hashes:
continue continue
if t is None or int(t.get('complete') or 0): current_label = '' if t is None else str(t.get('label') or '')
if _restore_auto_label(client, profile_id, h, None if t is None else str(t.get('label') or '')): if not _is_smart_queue_hold(t):
if _restore_auto_label(client, profile_id, h, None if t is None else current_label):
restored.append(h) restored.append(h)
continue continue
is_paused_or_stopped = bool(t.get('paused')) or not int(t.get('active') or 0) or not int(t.get('state') or 0) if current_label != SMART_QUEUE_LABEL:
current_label = str(t.get('label') or '') _set_smart_queue_label(client, h)
if is_paused_or_stopped:
if current_label != SMART_QUEUE_LABEL: for h, t in by_hash.items():
_set_smart_queue_label(client, h) if not h or h in keep_hashes or h in tracked_hashes or _is_smart_queue_hold(t):
continue continue
if _restore_auto_label(client, profile_id, h, current_label): if _clear_untracked_smart_queue_label(client, h, str(t.get('label') or '')):
restored.append(h) restored.append(h)
return restored return restored
@@ -228,8 +248,15 @@ def check(profile: dict | None = None, user_id: int | None = None, force: bool =
profile_id = int(profile['id']) profile_id = int(profile['id'])
settings = get_settings(profile_id, user_id) settings = get_settings(profile_id, user_id)
if not force and not int(settings.get('enabled') or 0): if not force and not int(settings.get('enabled') or 0):
add_history(profile_id, 'skipped_disabled', [], [], 0, {'enabled': False}, user_id) restored: list[str] = []
return {'ok': True, 'enabled': False, 'paused': [], 'resumed': [], 'message': 'Smart Queue disabled'} try:
# Note: Przy wyłączonym Smart Queue sprzątamy wyłącznie techniczne labele, bez startowania lub pauzowania torrentów.
torrents = rtorrent.list_torrents(profile)
restored = _cleanup_auto_labels(rtorrent.client_for(profile), profile_id, torrents, set())
except Exception:
restored = []
add_history(profile_id, 'skipped_disabled', [], [], 0, {'enabled': False, 'labels_restored': restored}, user_id)
return {'ok': True, 'enabled': False, 'paused': [], 'resumed': [], 'labels_restored': restored, 'message': 'Smart Queue disabled'}
torrents = rtorrent.list_torrents(profile) torrents = rtorrent.list_torrents(profile)
excluded = _excluded_hashes(profile_id, user_id) excluded = _excluded_hashes(profile_id, user_id)
@@ -310,7 +337,7 @@ def check(profile: dict | None = None, user_id: int | None = None, force: bool =
pass pass
for t in to_resume: for t in to_resume:
try: try:
# Note: Resume path explicitly removes Smart Queue auto label before and after start to cover stale cache labels. # Note: Wznowienie usuwa techniczny label przed startem i ponawia sprzątanie po starcie, gdy cache rTorrent jest opóźniony.
_restore_auto_label(c, profile_id, t['hash'], str(t.get('label') or '')) _restore_auto_label(c, profile_id, t['hash'], str(t.get('label') or ''))
c.call('d.resume', t['hash']) c.call('d.resume', t['hash'])
c.call('d.start', t['hash']) c.call('d.start', t['hash'])