aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/tests/test_transfer_slots_wire.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-08 22:54:16 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-08 22:54:16 +0200
commit6803447a8a5cc7a612d08bb858394fd7ae1b049c (patch)
tree565b2ceda2964f0e1395ea254df6014b116723ed /packages/meshbay-node/tests/test_transfer_slots_wire.py
parent051100ca32f72dd8f28489e1b6cb084f321b3b54 (diff)
downloadmeshbay-6803447a8a5cc7a612d08bb858394fd7ae1b049c.tar.gz
fix(node): a running transfer keeps its slot, and a dead grant lets go
Two defects in the lease machinery, both found in the node's own log, neither reachable from any test on either side. **`touch()` was never called.** The node ignored `tr` on `file_req` entirely, so `used` stayed False for every download ever made and the sweeper revoked each grant thirty seconds in — while the file was transferring at 20 MB/s. The pool was correct and the handlers were correct; the call between them was missing, which is why neither side's tests could see it. **The requeue was a permanent cycle.** A revoked grant went back in the queue, was granted again a millisecond later because there was room, and was revoked again thirty seconds on. The node logged the same two reclaims every thirty seconds for as long as it ran — minutes after the transfers involved had finished. Three chances now, then the lease is closed and the peer told. `test_the_counter_never_drifts` could not have caught it: nothing drifted, the same lease simply never left. A lease that starts being used forgets its earlier misses: a client that took two grants to get going is slow, not abandoned. Also `transfers show` reported the module defaults rather than the operator's values until something had transferred, so `transfers set 2 2` answered "applied now" and the next line said 0/8 — indistinguishable, from outside, from the hot-swap that did nothing for months. The test asserted the defaults and so agreed with the bug; found by typing the command. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HCGdheDLxGReuKHga3BtST
Diffstat (limited to 'packages/meshbay-node/tests/test_transfer_slots_wire.py')
-rw-r--r--packages/meshbay-node/tests/test_transfer_slots_wire.py48
1 files changed, 48 insertions, 0 deletions
diff --git a/packages/meshbay-node/tests/test_transfer_slots_wire.py b/packages/meshbay-node/tests/test_transfer_slots_wire.py
index afa4582..db8c17a 100644
--- a/packages/meshbay-node/tests/test_transfer_slots_wire.py
+++ b/packages/meshbay-node/tests/test_transfer_slots_wire.py
@@ -236,6 +236,25 @@ async def test_asking_before_anything_has_transferred_is_not_an_error():
assert snapshot["pools"][DOWNLOAD]["in_use"] == 0
+@pytest.mark.asyncio
+async def test_the_caps_shown_are_the_operators_before_anything_transfers():
+ """
+ `transfers set 2 2` answers "applied now"; `transfers show` said 0/8 —
+ because the no-pool branch reported the module defaults rather than what the
+ operator had just set. Found by running it against a real node. The previous
+ test asserted the defaults, so it agreed with the bug: an operator would
+ have read that as the hot-swap doing nothing all over again.
+ """
+ from meshbay_node import ops
+
+ class _T:
+ _ctx = {"max_concurrent_downloads": 2, "max_concurrent_uploads": 3}
+
+ snapshot = await ops.list_transfers({"webrtc": _T()})
+ assert snapshot["pools"][DOWNLOAD]["cap"] == 2
+ assert snapshot["pools"][UPLOAD]["cap"] == 3
+
+
# ── the sweeper's lifetime ──────────────────────────────────────────────────
async def test_the_sweeper_outlives_the_session_that_started_it(ctx):
@@ -296,3 +315,32 @@ async def test_the_sweeper_stops_when_the_last_lease_goes(ctx):
assert ctx.get("_transfer_sweeper") is None
finally:
ws.TRANSFER_SWEEP_SECS = original
+
+
+async def test_a_chunk_request_keeps_its_lease_alive(ctx):
+ """
+ The seam that cost an afternoon. `TransferSlots.touch` existed, was tested,
+ and **nothing ever called it**: the node ignored `tr` on `file_req`
+ entirely, so `used` stayed False for every download ever made and the
+ sweeper revoked each grant 30 s in, while the file was transferring.
+
+ Neither side's tests could see it — the pool was correct, the handlers were
+ correct, and the call between them was missing. Only the node's own log
+ showed it, repeating the same reclaim every 30 s.
+ """
+ peer = _join(ctx, "s1", "alice")
+ peer._do_transfer_open({"tr": "t1", "bytes": 1024})
+ lease = peer._slots().leases["t1"]
+ assert lease.used is False
+
+ # A chunk request for a file that does not exist still counts: what marks
+ # the lease is the peer asking, not the node succeeding.
+ peer._group_ctx()["index"] = None
+ try:
+ await peer._do_file_request({"file_id": "nope", "chunk_index": 0,
+ "tr": "t1"})
+ except Exception:
+ pass
+ assert peer._slots().leases["t1"].used is True, (
+ "a chunk request under this lease did not mark it alive; the node will "
+ "revoke the grant in 30 seconds")