aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src/meshbay_node/config.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-19 01:02:05 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-19 01:49:56 +0200
commitc2c49182e6d4f1f1ef3ed3ba5e8699912f9a27bd (patch)
tree026a7e4347d4580ed4914605019db50c5794a49b /packages/meshbay-node/src/meshbay_node/config.py
parent345a59fc128e5e4f253c277c8cee69a2b1062a4f (diff)
downloadmeshbay-c2c49182e6d4f1f1ef3ed3ba5e8699912f9a27bd.tar.gz
feat(node): per-file upload ceiling is an operator setting, default 8 GB
Was a 4 GB constant in webrtc_server.py, the same on a small board and on a machine holding a library. Now max_upload_gb in node.toml, on the Node page and via `meshbay-node transfers max-size`, read from the transport context per chunk so a change reaches an upload already running. MESHBAY_DESIGN.md §6.4; §15.3 records a defect found beside it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node/config.py')
-rw-r--r--packages/meshbay-node/src/meshbay_node/config.py37
1 files changed, 37 insertions, 0 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/config.py b/packages/meshbay-node/src/meshbay_node/config.py
index 086d800..bf62639 100644
--- a/packages/meshbay-node/src/meshbay_node/config.py
+++ b/packages/meshbay-node/src/meshbay_node/config.py
@@ -67,6 +67,13 @@ max_concurrent_streams = 8
max_concurrent_downloads = 8
max_concurrent_uploads = 8
+# The largest single file a member may upload to this node, in GB. It is this
+# machine's disk that fills, so the ceiling is the operator's to set: lower it
+# on a small disk, raise it for a library of films. Fractions are allowed
+# (0.5 = 512 MB). A file past it is refused at the chunk that crosses it and
+# the partial file is deleted.
+max_upload_gb = 8
+
# HEVC sources have no browser decoder on most platforms, so streaming one is
# transcoded to H264 rather than the usual free copy — real CPU per viewer.
# Set to false only if every viewer's client is known to decode HEVC itself.
@@ -181,6 +188,11 @@ class NodeConfig:
# answer "server busy". See meshbay_node/transfers.py.
max_concurrent_downloads: int = 8
max_concurrent_uploads: int = 8
+ # The per-file upload ceiling, in GB — the one limit here that bounds a
+ # member's writes to the operator's disk rather than this node's own
+ # concurrency. There is still no aggregate quota (MESHBAY_DESIGN.md
+ # §15.3), so this is what stands between a writable root and a full disk.
+ max_upload_gb: float = 8.0
# HEVC (and any future codec in media_probe.py's
# BROWSER_INCOMPATIBLE_VIDEO_CODECS) has no decoder in most browsers, so
# streaming it needs a real re-encode to H264 rather than the usual free
@@ -301,6 +313,28 @@ def _positive(value: object, default: int, name: str) -> int:
return n
+def _positive_float(value: object, default: float, name: str) -> float:
+ """A size that must be greater than zero, or the default with a word about it.
+
+ Separate from `_positive` because this one is a quantity, not a count: half
+ a gigabyte is a legitimate ceiling on a small disk, and rounding it to zero
+ would refuse every upload with nothing in the log to say why.
+ """
+ if isinstance(value, bool) or not isinstance(value, (int, float, str)):
+ log.warning("%s = %r is not a size — using %g", name, value, default)
+ return default
+ try:
+ n = float(value)
+ except (TypeError, ValueError):
+ log.warning("%s = %r is not a number — using %g", name, value, default)
+ return default
+ if n <= 0:
+ log.warning("%s = %g would refuse every upload — using %g",
+ name, n, default)
+ return default
+ return n
+
+
def _read_roots(group: dict) -> list[RootSpec]:
"""
A group's roots, from `[[groups.roots]]` or from the legacy `shared_dir`.
@@ -368,6 +402,9 @@ def load_config(path: Path = DEFAULT_CONFIG_PATH) -> Config:
cfg.node.max_concurrent_uploads = _positive(
nd.get("max_concurrent_uploads", cfg.node.max_concurrent_uploads),
cfg.node.max_concurrent_uploads, "max_concurrent_uploads")
+ cfg.node.max_upload_gb = _positive_float(
+ nd.get("max_upload_gb", cfg.node.max_upload_gb),
+ cfg.node.max_upload_gb, "max_upload_gb")
cfg.node.transcode_incompatible_video = bool(
nd.get("transcode_incompatible_video", cfg.node.transcode_incompatible_video))
cfg.node.hardware_video_encode = bool(