fix in peers

This commit is contained in:
Mateusz Gruszczyński
2026-06-09 11:19:14 +02:00
parent 16e3917fce
commit b2cede7b63
8 changed files with 759 additions and 305 deletions
+58 -9
View File
@@ -400,17 +400,42 @@ def list_torrents(profile: dict) -> list[dict]:
def torrent_peers(profile: dict, torrent_hash: str) -> list[dict]:
fields = [
"p.address=", "p.client_version=", "p.completed_percent=", "p.down_rate=",
"p.up_rate=", "p.port=", "p.is_encrypted=", "p.is_incoming=",
"p.is_snubbed=", "p.is_banned=",
]
PEER_DETAIL_FIELDS = [
"p.address=", "p.client_version=", "p.completed_percent=", "p.down_rate=",
"p.up_rate=", "p.port=", "p.is_encrypted=", "p.is_incoming=",
"p.is_snubbed=", "p.is_banned=",
]
PEER_DETAIL_FALLBACK_FIELDS = [
"p.address=", "p.client_version=", "p.completed_percent=", "p.down_rate=",
"p.up_rate=", "p.port=", "p.is_encrypted=",
]
PEER_ACTIVITY_FIELDS = ["d.peers_connected=", "d.up.rate=", "d.down.rate=", "d.is_active="]
def _peer_rows(c: ScgiRtorrentClient, torrent_hash: str) -> list:
try:
rows = client_for(profile).p.multicall(torrent_hash, "", *fields)
return c.p.multicall(torrent_hash, "", *PEER_DETAIL_FIELDS)
except Exception:
fields = ["p.address=", "p.client_version=", "p.completed_percent=", "p.down_rate=", "p.up_rate=", "p.port=", "p.is_encrypted="]
rows = client_for(profile).p.multicall(torrent_hash, "", *fields)
return c.p.multicall(torrent_hash, "", *PEER_DETAIL_FALLBACK_FIELDS)
def _peer_activity(c: ScgiRtorrentClient, torrent_hash: str) -> dict:
try:
values = c.d.multicall2("", "main", "d.hash=", *PEER_ACTIVITY_FIELDS)
for row in values:
if str(row[0] or "").lower() == str(torrent_hash or "").lower():
return {
"peers_connected": int(row[1] or 0),
"up_rate": int(row[2] or 0),
"down_rate": int(row[3] or 0),
"active": bool(row[4]),
}
except Exception:
pass
return {"peers_connected": 0, "up_rate": 0, "down_rate": 0, "active": False}
def _normalize_peer_rows(rows: list) -> list[dict]:
peers = []
for idx, r in enumerate(rows):
peers.append({
@@ -431,6 +456,30 @@ def torrent_peers(profile: dict, torrent_hash: str) -> list[dict]:
return peers
def torrent_peer_activity(profile: dict, torrent_hash: str) -> dict:
"""Return lightweight live counters used to decide whether an empty peer list may be stale."""
# Note: This is additive and does not change torrent list polling or cached torrent rows.
return _peer_activity(client_for(profile), torrent_hash)
def torrent_peers(profile: dict, torrent_hash: str, retry_when_active: bool = True) -> list[dict]:
c = client_for(profile)
rows = _peer_rows(c, torrent_hash)
if rows or not retry_when_active:
return _normalize_peer_rows(rows)
activity = _peer_activity(c, torrent_hash)
should_retry = bool(activity.get("peers_connected") or activity.get("up_rate") or activity.get("down_rate"))
if not should_retry:
return []
# Note: rTorrent can expose transfer counters before p.multicall catches up; short retries avoid a misleading empty peer table.
for _attempt in range(3):
time.sleep(0.2)
rows = _peer_rows(c, torrent_hash)
if rows:
return _normalize_peer_rows(rows)
return []
def _call_first(c: ScgiRtorrentClient, candidates: list[tuple[str, tuple]]) -> dict: