light poller commit1
This commit is contained in:
@@ -217,6 +217,13 @@ TORRENT_OPTIONAL_FIELDS = [
|
||||
"d.timestamp.finished=",
|
||||
]
|
||||
|
||||
LIVE_TORRENT_FIELDS = [
|
||||
"d.hash=", "d.state=", "d.complete=", "d.size_bytes=", "d.completed_bytes=",
|
||||
"d.ratio=", "d.up.rate=", "d.down.rate=", "d.up.total=", "d.down.total=",
|
||||
"d.peers_connected=", "d.peers_complete=", "d.message=", "d.hashing=", "d.is_active=",
|
||||
"d.custom1=",
|
||||
]
|
||||
|
||||
|
||||
def human_duration(seconds: int) -> str:
|
||||
# Note: Download ETA is derived locally from remaining bytes and current download speed.
|
||||
@@ -313,6 +320,65 @@ def normalize_row(row: list) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def normalize_live_row(row: list) -> dict:
|
||||
"""Normalize the small row used by the fast live stats poller."""
|
||||
# Note: The live poller intentionally reads only volatile fields so the main list poller can run less often.
|
||||
size = int(row[3] or 0)
|
||||
completed = int(row[4] or 0)
|
||||
complete = int(row[2] or 0)
|
||||
state = int(row[1] or 0)
|
||||
down_rate = int(row[7] or 0)
|
||||
up_rate = int(row[6] or 0)
|
||||
ratio_raw = int(row[5] or 0)
|
||||
remaining_bytes = max(0, size - completed)
|
||||
eta_seconds = int(remaining_bytes / down_rate) if down_rate > 0 and not complete else 0
|
||||
msg = str(row[12] or "")
|
||||
hashing = int(row[13] or 0)
|
||||
is_active = int(row[14] or 0)
|
||||
labels = str(row[15] or "")
|
||||
is_checking = bool(hashing) or _message_indicates_active_check(msg.lower())
|
||||
post_check = POST_CHECK_DOWNLOAD_LABEL in _label_names(labels) and not is_checking and not bool(is_active)
|
||||
is_paused = bool(state) and not bool(is_active) and not is_checking and not post_check
|
||||
status = "Checking" if is_checking else "Post-check" if post_check else "Paused" if is_paused else "Seeding" if complete and state else "Downloading" if state else "Stopped"
|
||||
progress = 100.0 if size <= 0 and complete else round((completed / size) * 100, 2) if size else 0.0
|
||||
to_download_bytes = remaining_bytes if not complete else 0
|
||||
return {
|
||||
"hash": str(row[0] or ""),
|
||||
"state": state,
|
||||
"active": is_active,
|
||||
"paused": is_paused,
|
||||
"complete": complete,
|
||||
"completed_bytes": completed,
|
||||
"progress": progress,
|
||||
"ratio": round(ratio_raw / 1000, 3),
|
||||
"up_rate": up_rate,
|
||||
"up_rate_h": human_rate(up_rate),
|
||||
"down_rate": down_rate,
|
||||
"down_rate_h": human_rate(down_rate),
|
||||
"eta_seconds": eta_seconds,
|
||||
"eta_h": human_duration(eta_seconds) if eta_seconds else "-",
|
||||
"up_total": int(row[8] or 0),
|
||||
"up_total_h": human_size(row[8] or 0),
|
||||
"down_total": int(row[9] or 0),
|
||||
"down_total_h": human_size(row[9] or 0),
|
||||
"to_download": to_download_bytes,
|
||||
"to_download_h": human_size(to_download_bytes) if to_download_bytes else "",
|
||||
"peers": int(row[10] or 0),
|
||||
"seeds": int(row[11] or 0),
|
||||
"message": msg,
|
||||
"status": status,
|
||||
"post_check": post_check,
|
||||
"hashing": hashing,
|
||||
}
|
||||
|
||||
|
||||
def list_torrent_live_stats(profile: dict) -> list[dict]:
|
||||
"""Return lightweight live torrent stats for the fast poller."""
|
||||
# Note: This avoids the full torrent row multicall on every speed/status tick.
|
||||
rows = client_for(profile).d.multicall2("", "main", *LIVE_TORRENT_FIELDS)
|
||||
return [normalize_live_row(list(row)) for row in rows]
|
||||
|
||||
|
||||
def list_torrents(profile: dict) -> list[dict]:
|
||||
c = client_for(profile)
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user