fix ququq
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
|
||||
from .client import *
|
||||
from .files import set_file_priorities
|
||||
from .system import disk_usage_for_default_path
|
||||
@@ -214,6 +216,7 @@ TORRENT_FIELDS = [
|
||||
]
|
||||
|
||||
TORRENT_OPTIONAL_FIELDS = [
|
||||
"d.timestamp.last_active=",
|
||||
"d.timestamp.finished=",
|
||||
]
|
||||
|
||||
@@ -252,7 +255,12 @@ def normalize_row(row: list) -> dict:
|
||||
directory = str(row[14] or "")
|
||||
base_path = str(row[15] or "")
|
||||
is_multi_file = int(row[22] or 0) if len(row) > 22 else 0
|
||||
completed_at = int(row[23] or 0) if len(row) > 23 else 0
|
||||
# Note: Last activity is optional because older rTorrent builds may not expose this timestamp.
|
||||
last_activity = int(row[23] or 0) if len(row) > 23 else 0
|
||||
if not last_activity and (down_rate > 0 or up_rate > 0):
|
||||
# Note: rTorrent builds without d.timestamp.last_active still expose live rates, so active rows get a safe current timestamp.
|
||||
last_activity = int(time.time())
|
||||
completed_at = int(row[24] or 0) if len(row) > 24 else 0
|
||||
|
||||
# Show the selected download location only. Hide the torrent root
|
||||
# directory for multi-file torrents and the filename for single-file
|
||||
@@ -310,6 +318,7 @@ def normalize_row(row: list) -> dict:
|
||||
"priority": int(row[13] or 0),
|
||||
"path": display_path,
|
||||
"created": int(row[16] or 0),
|
||||
"last_activity": last_activity,
|
||||
"completed_at": completed_at,
|
||||
"label": str(row[17] or ""),
|
||||
"ratio_group": str(row[18] or ""),
|
||||
|
||||
@@ -66,6 +66,8 @@ def _diagnostics_torrent(t: dict[str, Any] | None) -> dict[str, Any]:
|
||||
'hashing': int(t.get('hashing') or 0),
|
||||
'priority': int(t.get('priority') or 0),
|
||||
'down_rate': int(t.get('down_rate') or 0),
|
||||
'up_rate': int(t.get('up_rate') or 0),
|
||||
'last_activity': int(t.get('last_activity') or 0),
|
||||
'peers': int(t.get('peers') or 0),
|
||||
'seeds': int(t.get('seeds') or 0),
|
||||
'label': str(t.get('label') or ''),
|
||||
@@ -800,9 +802,22 @@ def _is_running_download_slot(t: dict[str, Any]) -> bool:
|
||||
return _is_started_download_slot(t)
|
||||
|
||||
|
||||
def _is_stalled_download(t: dict[str, Any], min_speed: int, min_seeds: int, min_peers: int, ignore_seed_peer: bool, ignore_speed: bool) -> bool:
|
||||
def _has_recent_transfer_activity(t: dict[str, Any], stalled_seconds: int) -> bool:
|
||||
"""Return True when a torrent is currently transferring or was active within the stalled window."""
|
||||
# Note: Live transfer rates always protect a torrent from being marked as stalled.
|
||||
if int(t.get('down_rate') or 0) > 0 or int(t.get('up_rate') or 0) > 0:
|
||||
return True
|
||||
last_activity = int(t.get('last_activity') or 0)
|
||||
if last_activity <= 0:
|
||||
return False
|
||||
return time.time() - last_activity < max(1, int(stalled_seconds or 0))
|
||||
|
||||
|
||||
def _is_stalled_download(t: dict[str, Any], min_speed: int, min_seeds: int, min_peers: int, stalled_seconds: int, ignore_seed_peer: bool, ignore_speed: bool) -> bool:
|
||||
"""Return True when a started torrent should begin or continue the stalled timer."""
|
||||
# Note: Each ignore switch removes only its own criterion; the stalled timer still applies after criteria match.
|
||||
# Note: Recent transfer activity wins over ignored source/speed criteria, preventing active torrents from being stopped as stalled.
|
||||
if _has_recent_transfer_activity(t, stalled_seconds):
|
||||
return False
|
||||
speed_ok = True if ignore_speed else int(t.get('down_rate') or 0) <= max(0, int(min_speed or 0))
|
||||
source_ok = True if ignore_seed_peer else int(t.get('seeds') or 0) <= max(0, int(min_seeds or 0)) and (min_peers <= 0 or int(t.get('peers') or 0) <= min_peers)
|
||||
return speed_ok and source_ok
|
||||
@@ -810,13 +825,15 @@ def _is_stalled_download(t: dict[str, Any], min_speed: int, min_seeds: int, min_
|
||||
|
||||
def _stalled_timer_key(min_speed: int, min_seeds: int, min_peers: int, stalled_seconds: int, ignore_seed_peer: bool, ignore_speed: bool) -> str:
|
||||
"""Return a stable key for the stalled rules that started the current timer."""
|
||||
# Note: Changing ignore switches or thresholds restarts existing stalled timers instead of reusing old rows.
|
||||
return f"v4|speed={int(min_speed or 0)}|seeds={int(min_seeds or 0)}|peers={int(min_peers or 0)}|seconds={int(stalled_seconds or 0)}|ignore_sources={int(bool(ignore_seed_peer))}|ignore_speed={int(bool(ignore_speed))}"
|
||||
# Note: Version bump clears old timers created by the previous ignore-speed/source behavior.
|
||||
return f"v5|speed={int(min_speed or 0)}|seeds={int(min_seeds or 0)}|peers={int(min_peers or 0)}|seconds={int(stalled_seconds or 0)}|ignore_sources={int(bool(ignore_seed_peer))}|ignore_speed={int(bool(ignore_speed))}"
|
||||
|
||||
|
||||
def _is_low_activity_download(t: dict[str, Any], min_speed: int, min_seeds: int, min_peers: int, ignore_seed_peer: bool = False, ignore_speed: bool = False) -> bool:
|
||||
def _is_low_activity_download(t: dict[str, Any], min_speed: int, min_seeds: int, min_peers: int, stalled_seconds: int, ignore_seed_peer: bool = False, ignore_speed: bool = False) -> bool:
|
||||
"""Return True when a started torrent is weak and should be stopped first."""
|
||||
# Note: Stop priority uses only criteria that are not ignored, so disabled criteria cannot stop torrents earlier.
|
||||
# Note: Active transfers are never preferred for cleanup while non-transferring rows are available.
|
||||
if _has_recent_transfer_activity(t, stalled_seconds):
|
||||
return False
|
||||
low_speed = False if ignore_speed else int(t.get('down_rate') or 0) <= max(0, int(min_speed or 0))
|
||||
low_seeds = False if ignore_seed_peer else int(t.get('seeds') or 0) <= max(0, int(min_seeds or 0))
|
||||
low_peers = False if ignore_seed_peer or min_peers <= 0 else int(t.get('peers') or 0) <= max(0, int(min_peers or 0))
|
||||
@@ -1232,9 +1249,9 @@ def check(profile: dict | None = None, user_id: int | None = None, force: bool =
|
||||
ignored_seed_peer_count += 1
|
||||
if ignore_speed and int(t.get('down_rate') or 0) <= max(0, int(min_speed or 0)):
|
||||
ignored_speed_count += 1
|
||||
is_stalled = _is_stalled_download(t, min_speed, min_seeds, min_peers, ignore_seed_peer, ignore_speed)
|
||||
is_stalled = _is_stalled_download(t, min_speed, min_seeds, min_peers, stalled_seconds, ignore_seed_peer, ignore_speed)
|
||||
# Note: Hard-limit enforcement uses only non-ignored weak criteria before choosing weak items.
|
||||
if _is_low_activity_download(t, min_speed, min_seeds, min_peers, ignore_seed_peer, ignore_speed):
|
||||
if _is_low_activity_download(t, min_speed, min_seeds, min_peers, stalled_seconds, ignore_seed_peer, ignore_speed):
|
||||
stop_eligible.append(t)
|
||||
h = str(t.get('hash') or '')
|
||||
if not h:
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -100,7 +100,7 @@
|
||||
<th data-sort="down_rate" data-col="down_rate">DL</th><th data-sort="up_rate" data-col="up_rate">UL</th><th data-sort="eta" data-col="eta">ETA</th><th data-sort="seeds" data-col="seeds">Seeds</th><th data-sort="peers" data-col="peers">Peers</th>
|
||||
<th data-sort="ratio" data-col="ratio">Ratio</th><th data-sort="path" data-col="path">Path</th><th data-sort="label" data-col="label">Label</th><th data-sort="ratio_group" data-col="ratio_group">Ratio group</th><th data-sort="down_total" data-col="down_total">Downloaded</th><th data-sort="to_download" data-col="to_download">To download</th><th data-sort="up_total" data-col="up_total">Uploaded</th><th data-sort="created" data-col="created">Added</th><th data-sort="priority" data-col="priority">Priority</th><th data-sort="state" data-col="state">State</th><th data-sort="active" data-col="active">Active</th><th data-sort="complete" data-col="complete">Complete</th><th data-sort="hashing" data-col="hashing">Hashing</th><th data-sort="message" data-col="message">Message</th><th data-sort="hash" data-col="hash">Hash</th>
|
||||
</tr></thead>
|
||||
<tbody id="torrentBody"><tr><td colspan="25" class="empty"><span class="spinner-border spinner-border-sm me-2"></span>Waiting for data.</td></tr></tbody>
|
||||
<tbody id="torrentBody"><tr><td colspan="26" class="empty"><span class="spinner-border spinner-border-sm me-2"></span>Waiting for data.</td></tr></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id="mobileFilterBar" class="mobile-filter-bar d-none" aria-label="Torrent filters"></div>
|
||||
|
||||
Reference in New Issue
Block a user