smart queue fix
This commit is contained in:
@@ -164,10 +164,17 @@ def _restore_auto_label(client: Any, profile_id: int, torrent_hash: str, current
|
|||||||
'SELECT previous_label FROM smart_queue_auto_labels WHERE profile_id=? AND torrent_hash=?',
|
'SELECT previous_label FROM smart_queue_auto_labels WHERE profile_id=? AND torrent_hash=?',
|
||||||
(profile_id, torrent_hash),
|
(profile_id, torrent_hash),
|
||||||
).fetchone()
|
).fetchone()
|
||||||
if not row:
|
|
||||||
return False
|
|
||||||
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 '')
|
||||||
|
if not row:
|
||||||
|
if live_label != SMART_QUEUE_LABEL:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
# Note: Czyści label Smart Queue także wtedy, gdy torrent został oznaczony wcześniej, ale nie ma już wpisu z poprzednim labelem.
|
||||||
|
client.call('d.custom1.set', torrent_hash, '')
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
previous = row.get('previous_label') or ''
|
||||||
try:
|
try:
|
||||||
# Note: Przy wznowieniu Smart Queue oddaje poprzedni label tylko wtedy, gdy nadal widzi swój label techniczny.
|
# 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:
|
||||||
@@ -266,16 +273,23 @@ def _verify_started_downloads(client: Any, hashes: list[str], attempts: int = 3,
|
|||||||
|
|
||||||
def _read_live_start_state(client: Any, torrent_hash: str) -> dict[str, Any]:
|
def _read_live_start_state(client: Any, torrent_hash: str) -> dict[str, Any]:
|
||||||
result: dict[str, Any] = {'hash': torrent_hash}
|
result: dict[str, Any] = {'hash': torrent_hash}
|
||||||
for key, method in (('state', 'd.state'), ('active', 'd.is_active'), ('message', 'd.message')):
|
fields = (
|
||||||
|
('state', 'd.state'),
|
||||||
|
('active', 'd.is_active'),
|
||||||
|
('open', 'd.is_open'),
|
||||||
|
('priority', 'd.priority'),
|
||||||
|
('message', 'd.message'),
|
||||||
|
('label', 'd.custom1'),
|
||||||
|
)
|
||||||
|
for key, method in fields:
|
||||||
try:
|
try:
|
||||||
value = client.call(method, torrent_hash)
|
value = client.call(method, torrent_hash)
|
||||||
result[key] = int(value or 0) if key in {'state', 'active'} else str(value or '')
|
result[key] = int(value or 0) if key in {'state', 'active', 'open', 'priority'} else str(value or '')
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
result[f'{key}_error'] = str(exc)
|
result[f'{key}_error'] = str(exc)
|
||||||
# Note: rTorrent po masowym d.resume/d.start potrafi długo zwracać d.is_active=0
|
# Note: Nie uznajemy samego state=1 za aktywny start, bo paused w rTorrent też potrafi mieć state=1.
|
||||||
# dla torrentów bez bieżącego transferu. Dla Smart Queue start oznacza state=1;
|
# Sukces techniczny Smart Queue jest zapisywany po zaakceptowanym RPC, a ta funkcja służy tylko do diagnostyki.
|
||||||
# inaczej weryfikacja zalicza tylko 1 pozycję i kolejne przebiegi dokładają po jednej sztuce.
|
result['started'] = bool(int(result.get('active') or 0) or int(result.get('open') or 0))
|
||||||
result['started'] = bool(int(result.get('state') or 0))
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _set_smart_queue_label(client: Any, torrent_hash: str, attempts: int = 3) -> bool:
|
def _set_smart_queue_label(client: Any, torrent_hash: str, attempts: int = 3) -> bool:
|
||||||
@@ -511,7 +525,8 @@ def check(profile: dict | None = None, user_id: int | None = None, force: bool =
|
|||||||
except Exception:
|
except Exception:
|
||||||
label_failed.append(h)
|
label_failed.append(h)
|
||||||
|
|
||||||
# Note: Startujemy całą pulę kandydatów w jednej rundzie, a dopiero potem weryfikujemy efekt.
|
# Note: Startujemy całą pulę kandydatów w jednej rundzie. Label zdejmujemy po zaakceptowanym RPC,
|
||||||
|
# bo rTorrent może trzymać część pozycji w swojej kolejce z active=0 mimo poprawnego d.start/d.resume.
|
||||||
for t in to_resume:
|
for t in to_resume:
|
||||||
h = str(t.get('hash') or '')
|
h = str(t.get('hash') or '')
|
||||||
if not h:
|
if not h:
|
||||||
@@ -519,19 +534,18 @@ def check(profile: dict | None = None, user_id: int | None = None, force: bool =
|
|||||||
try:
|
try:
|
||||||
_start_download(c, t)
|
_start_download(c, t)
|
||||||
resume_requested.append(h)
|
resume_requested.append(h)
|
||||||
|
_restore_auto_label(c, profile_id, h, None)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
start_failed.append({'hash': h, 'error': str(exc)})
|
start_failed.append({'hash': h, 'error': str(exc)})
|
||||||
|
|
||||||
verified, start_no_effect = _verify_started_downloads(c, resume_requested)
|
active_verified, start_no_effect = _verify_started_downloads(c, resume_requested)
|
||||||
for h in verified:
|
resumed = list(resume_requested)
|
||||||
_restore_auto_label(c, profile_id, h, None)
|
|
||||||
resumed = verified
|
|
||||||
keep_labels = (
|
keep_labels = (
|
||||||
set(paused)
|
set(paused)
|
||||||
| {str(t.get('hash') or '') for t in to_label_waiting}
|
| {str(t.get('hash') or '') for t in to_label_waiting}
|
||||||
| {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)}
|
| {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)
|
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, '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': active_after_pause + len(resumed), 'rtorrent_cap': rtorrent_cap}
|
||||||
add_history(profile_id, 'force_check' if force else 'auto_check', paused, resumed, len(torrents), details, user_id)
|
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, 'rtorrent_cap': rtorrent_cap, 'checked': len(torrents), 'excluded': len(excluded), 'settings': settings}
|
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}
|
||||||
|
|||||||
Reference in New Issue
Block a user