aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src/meshbay_node/uploads.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-01 13:24:11 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-01 13:24:11 +0200
commit1d6189b6e6db7d0d6c126717b081901c5f552174 (patch)
tree69e6e791e234c1c2b6a2dc91808ac44d81aaecae /packages/meshbay-node/src/meshbay_node/uploads.py
parentf0019e366fef813b22d2d55cf7604e20f0a08707 (diff)
downloadmeshbay-1d6189b6e6db7d0d6c126717b081901c5f552174.tar.gz
fix(node): the reaper deletes only the .part files the node wrote
Any *.part older than a day in a writable root was deleted — a browser's download in progress in a shared folder included. Only names carrying the node's tag (name.<8 hex>.part) are reaped now (F-28). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node/uploads.py')
-rw-r--r--packages/meshbay-node/src/meshbay_node/uploads.py13
1 files changed, 12 insertions, 1 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/uploads.py b/packages/meshbay-node/src/meshbay_node/uploads.py
index 92b854e..c485e39 100644
--- a/packages/meshbay-node/src/meshbay_node/uploads.py
+++ b/packages/meshbay-node/src/meshbay_node/uploads.py
@@ -24,6 +24,7 @@ build first.
from __future__ import annotations
+import re
import secrets
import time
from collections.abc import Iterable
@@ -45,6 +46,16 @@ def part_name(stored_name: str) -> str:
"""
return f"{stored_name}.{secrets.token_hex(4)}{PART_SUFFIX}"
+
+# What `part_name` writes, and the only thing the reaper deletes. A `.part`
+# without the node's tag is somebody else's — a browser's download in progress in
+# a shared folder, a copy the operator is making — and is never touched.
+_OWN_PART = re.compile(r"\.[0-9a-f]{8}" + re.escape(PART_SUFFIX) + r"$")
+
+
+def is_own_part(path: Path) -> bool:
+ return bool(_OWN_PART.search(path.name))
+
# How long a `.part` with no upload behind it is kept before it is deleted.
#
# Generous on purpose. The cost of waiting is disk; the cost of being wrong is
@@ -165,7 +176,7 @@ def orphaned_parts(candidates: Iterable[tuple[Path, float]],
"""
doomed: list[Path] = []
for path, mtime in candidates:
- if path.suffix != PART_SUFFIX:
+ if not is_own_part(path):
continue
if path in live:
continue