fix model DL doe 4-th time

This commit is contained in:
Dobromir Popov
2026-07-06 22:38:57 +03:00
parent 4f007aeef9
commit 7e7682be47
4 changed files with 106 additions and 14 deletions

View File

@@ -0,0 +1,58 @@
# US-047 — Model-source race: visibility, sane timeouts, quiet tracker aborts
Status: in progress
Priority: High (follow-up to US-044/US-046; blocks usable LAN downloads)
## Context
Reported 2026-07-06 (Windows CPU node, 79.2 GB RAM, `--tracker
http://192.168.0.179:8080 --model Qwen3.6-35B-A3B`):
1. Startup prints `(auto-join unavailable: HTTP Error 503)` even though the
user explicitly named a model. The auto-join query (`/v1/network/assign`)
never sends the requested model, so a fresh tracker + a caller too small
for the *recommended* preset 503s (expected per US-046) — but the whole
auto-join step is pointless when the user already picked a model: the
`/v1/nodes/assign?model=…` call right after it succeeds (assigned layers
02 with tracker `model_sources`).
2. The tracker-vs-HuggingFace race then starts, but only HuggingFace shows
progress (hf tqdm bars). The tracker tar download prints nothing and
swallows every failure (`except Exception: return None`), so the node
*appears* to download only from slow HF; the user killed it. Tracker-side
log showed the tar stream reset mid-`archive.add` — with no way to tell
whether the client timed out or the user aborted.
3. `_download_model_source` inherits `peer_timeout` (2.0 s) as its urlopen
socket timeout. Any 2 s read stall during a multi-GB tar stream silently
kills the tracker source and leaves HF as the only contender.
4. Every client abort spams the tracker console with a full
`BrokenPipeError`/`ConnectionResetError` traceback from `socketserver`.
## Fix
1. `startup.py`: skip the network auto-join query entirely when a model was
explicitly requested (`model` set and not `"stub-model"`); path 3b
(`/v1/nodes/assign?model=…`) is the authoritative one there.
2. `downloader.py`: model-source downloads get their own timeout constant
(30 s socket timeout) instead of the 2 s peer-probe timeout. Peer shard
downloads keep 2 s — they run sequentially before the race, and a dead
peer must not hang startup for 30 s; the race is concurrent so a slow
source costs nothing.
3. `downloader.py`: progress + failure visibility for the race —
`_download_model_source` prints received bytes every 512 MB and prints
the exception when a source fails, so "downloads only from HF" can never
happen silently again.
4. Tracker `_handle_model_files_download`: catch
`BrokenPipeError`/`ConnectionResetError` around the tar stream and log a
single line instead of a traceback.
## Acceptance criteria
- [ ] Node started with an explicit `--model` never queries
`/v1/network/assign` and never prints `auto-join unavailable`.
- [ ] During the race, tracker-source progress lines appear alongside HF
tqdm output; a failing tracker source prints its exception.
- [ ] A ≥2 s read stall no longer aborts a tracker model-source download
(30 s socket timeout).
- [ ] Client disconnect during `/v1/model-files/download` logs one line on
the tracker, no traceback.
- [ ] `python -m pytest` passes from repo root.