rtorrent config

This commit is contained in:
Mateusz Gruszczyński
2026-05-31 12:13:45 +02:00
parent 62bc76e806
commit 5fbc2428b6
3 changed files with 74 additions and 14 deletions
+67 -13
View File
@@ -86,6 +86,15 @@ RTORRENT_CONFIG_FIELDS = [
"description": "Maximum simultaneous HTTP connections for tracker and metadata requests.",
"recommendation": "Moderate values reduce tracker pressure; increase only if tracker requests queue up.",
},
{
"group": "Network",
"key": "network.http.dns_cache_timeout",
"label": "HTTP DNS cache timeout",
"type": "number",
"description": "Seconds rTorrent keeps DNS results for tracker and HTTP requests.",
"recommendation": "Use a small positive value, for example 25, when many tracker hostnames are queried repeatedly.",
"runtime_note": "Applied through SCGI immediately; new HTTP lookups use the updated timeout.",
},
{
"group": "Network",
"key": "network.http.ssl_verify_peer",
@@ -162,34 +171,65 @@ RTORRENT_CONFIG_FIELDS = [
{
"group": "Throttle",
"key": "throttle.max_downloads.global",
"label": "Max active downloads",
"label": "Global download slots",
"type": "number",
"description": "Maximum number of downloading torrents active at once.",
"recommendation": "Match disk and network capacity; fewer active downloads often finish faster.",
"description": "Global number of peer download slots across all torrents; this is not the active torrent count.",
"recommendation": "Raise this on large instances so a few busy torrents do not starve the rest.",
"runtime_note": "Applied through SCGI immediately; existing peer scheduling catches up gradually.",
},
{
"group": "Throttle",
"key": "throttle.max_uploads.global",
"label": "Max active uploads",
"label": "Global upload slots",
"type": "number",
"description": "Maximum number of uploading torrents active at once.",
"recommendation": "Keep enough slots for ratio goals without overloading disks and sockets.",
"description": "Global number of peer upload slots across all torrents; this is not the active torrent count.",
"recommendation": "Keep enough slots for many seeds, but stay below socket and file descriptor limits.",
"runtime_note": "Applied through SCGI immediately; current peer connections may rebalance over time.",
},
{
"group": "Throttle",
"key": "throttle.max_downloads",
"label": "Per-torrent download slots",
"type": "number",
"description": "Maximum peer download slots allowed for a single torrent in the default throttle group.",
"recommendation": "Use values like 5-20 to prevent one torrent from consuming all global download slots.",
"runtime_note": "Applied through SCGI immediately; it affects new and rebalanced peer slot allocation.",
},
{
"group": "Throttle",
"key": "throttle.max_uploads",
"label": "Per-torrent upload slots",
"type": "number",
"description": "Maximum peer upload slots allowed for a single torrent in the default throttle group.",
"recommendation": "Use conservative values on very large seedboxes so many seeds can stay reachable.",
"runtime_note": "Applied through SCGI immediately; it affects new and rebalanced peer slot allocation.",
},
{
"group": "Throttle",
"key": "throttle.max_downloads.div",
"label": "Max downloads per throttle",
"label": "Download slot divisor",
"type": "number",
"description": "Per-throttle download slot divisor used by rTorrent throttling logic.",
"recommendation": "Change only when using named throttle groups or advanced queues.",
"recommendation": "Keep at 1 unless you intentionally use advanced throttle groups.",
"runtime_note": "Applied through SCGI immediately for the default throttle scheduler.",
},
{
"group": "Throttle",
"key": "throttle.max_uploads.div",
"label": "Max uploads per throttle",
"label": "Upload slot divisor",
"type": "number",
"description": "Per-throttle upload slot divisor used by rTorrent throttling logic.",
"recommendation": "Change only when using named throttle groups or advanced queues.",
"recommendation": "Keep at 1 unless you intentionally use advanced throttle groups.",
"runtime_note": "Applied through SCGI immediately for the default throttle scheduler.",
},
{
"group": "Ratio",
"key": "ratio.max",
"label": "Global ratio max",
"type": "number",
"description": "Global maximum ratio value used by rTorrent ratio logic where enabled.",
"recommendation": "Use -1 for no global cap, or manage per-profile ratio policies from pyTorrent when possible.",
"runtime_note": "Applied through SCGI immediately when the rTorrent ratio method is available.",
},
{
"group": "DHT / PEX",
@@ -410,6 +450,19 @@ def default_download_path(profile: dict) -> str:
errors.append(f"{method}: {exc}")
raise RuntimeError("Cannot read rTorrent default download directory: " + "; ".join(errors))
def _rtorrent_set_method(key: str, meta: dict) -> str:
# Note: Most runtime values use the conventional <method>.set setter.
# Some rTorrent commands, such as protocol.encryption.set, are already
# setter commands and must not receive another .set suffix.
return str(meta.get("set_method") or (key if key.endswith(".set") else f"{key}.set"))
def _rtorrent_config_line_key(key: str, meta: dict) -> str:
# Note: Generated snippets must match rTorrent config syntax and avoid
# producing invalid protocol.encryption.set.set lines.
return str(meta.get("config_key") or _rtorrent_set_method(key, meta))
def generate_config_text(values: dict) -> str:
known = {f["key"]: f for f in RTORRENT_CONFIG_FIELDS}
lines = []
@@ -420,7 +473,7 @@ def generate_config_text(values: dict) -> str:
normalized = _normalize_config_value(meta, value)
if meta.get("type") == "text" and any(ch.isspace() for ch in normalized):
normalized = '"' + normalized.replace('\\', '\\\\').replace('"', '\\"') + '"'
lines.append(f"{key}.set = {normalized}")
lines.append(f"{_rtorrent_config_line_key(key, meta)} = {normalized}")
return "\n".join(lines) + ("\n" if lines else "")
@@ -506,10 +559,11 @@ def set_config(profile: dict, values: dict, apply_now: bool = True, apply_on_sta
value = _normalize_config_value(meta, raw_value)
rpc_value = int(value) if meta.get("type") in {"bool", "number"} else value
try:
method = _rtorrent_set_method(key, meta)
try:
c.call(key + ".set", "", rpc_value)
c.call(method, "", rpc_value)
except Exception:
c.call(key + ".set", rpc_value)
c.call(method, rpc_value)
updated.append(key)
except Exception as exc:
errors.append({"key": key, "error": str(exc)})