feat(us-022): X-Meshnet-Start-Layer pipeline protocol for overlapping shards

When _select_route picks two nodes with overlapping registrations (e.g.
A:0-22 and B:20-24), the tracker now injects start_layer per hop so B
executes only layers 23-24, not 20-24.

- model_backend: forward_bytes + _run_layers accept start_layer offset;
  clamped to shard_start to prevent out-of-bounds indexing
- torch_server: _handle_binary_forward reads X-Meshnet-Start-Layer header;
  _run_downstream_pipeline sends it per hop; route is now list[tuple[str,int]]
- server: proxy injects {endpoint, start_layer} objects in X-Meshnet-Route;
  /v1/route response includes start_layer per node in the nodes list
- test: fake backends accept start_layer=None kwarg

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Dobromir Popov
2026-06-30 13:14:45 +03:00
parent e1ba120912
commit 96af82892f
4 changed files with 82 additions and 20 deletions

View File

@@ -728,8 +728,16 @@ class _TrackerHandler(http.server.BaseHTTPRequestHandler):
]
rs, re = 0, (max((n.num_layers for n in all_nodes), default=1) - 1)
route_nodes, _ = _select_route(all_nodes, rs, re)
# Compute start_layer for each hop: each node begins where the previous ended + 1.
# This allows overlapping shard registrations without double-computation.
covered_up_to = rs - 1
route_hops: list[dict] = []
for rn in route_nodes:
route_hops.append({"endpoint": rn.endpoint, "start_layer": covered_up_to + 1})
covered_up_to = rn.shard_end if rn.shard_end is not None else covered_up_to
# Strip the first-shard node we're about to proxy to — it's already handling the request.
downstream_urls = json.dumps([n.endpoint for n in route_nodes if n.endpoint != node.endpoint])
downstream_hops = [h for h in route_hops if h["endpoint"].rstrip("/") != node.endpoint.rstrip("/")]
downstream_urls = json.dumps(downstream_hops)
route_debug = " -> ".join(
f"{n.node_id}@{n.endpoint}[{n.shard_start}-{n.shard_end}]"
for n in route_nodes
@@ -1334,12 +1342,19 @@ class _TrackerHandler(http.server.BaseHTTPRequestHandler):
self._send_json(503, {"error": error})
return
covered_up_to = required_start - 1
route_with_start: list[tuple] = []
for rn in route:
route_with_start.append((rn, covered_up_to + 1))
covered_up_to = rn.shard_end if rn.shard_end is not None else covered_up_to
self._send_json(200, {
"route": [e.endpoint for e in route],
"route": [e.endpoint for e, _ in route_with_start],
"nodes": [
{
"node_id": e.node_id,
"endpoint": e.endpoint,
"start_layer": start,
"wallet_address": e.wallet_address,
"shard_start": e.shard_start,
"shard_end": e.shard_end,
@@ -1347,7 +1362,7 @@ class _TrackerHandler(http.server.BaseHTTPRequestHandler):
"shard_checksum": e.shard_checksum,
"score": e.score,
}
for e in route
for e, start in route_with_start
],
})