Say why a Xet download sits at 0% until it finishes - #9159
Conversation
Xet fetches a model as parallel chunks and commits them in batches, so progress reads 0% for a while and then completes at once. That looks like a hung download, and it is the most common complaint about Xet. Toast the reason on the first three model downloads that start on Xet, and point at the HTTP transport in Model Hub for anyone who wants steadier progress. The count is stored, with an in-memory carry so a browser that refuses the write does not repeat the toast on every download.
The start endpoints accept a second client for a job already running and report that job's transport, which is indistinguishable from a fresh Xet start. Both now say which it was, so an attaching tab neither shows the notice nor spends one of the three.
The routes set response_model, so a key the schema does not name is dropped before it reaches the browser. The flag shipped in the handler but never in the response, leaving the notice gate reading undefined.
A cancel can land while the start POST is in flight: the start still comes back accepted, so the notice promised a running download the user had just stopped, and spent one of the three doing it.
The reject branch also covers a cross-variant conflict and an in-progress delete, which join nothing. Both flags now come from the adoptable verdict.
|
@codex review |
Two tabs starting a download at the same moment both read the count before either wrote it, so a fourth toast could appear. Web Locks make the read and the write one step; browsers without them keep the old bounded race.
|
@codex review |
|
Codex Review: Didn't find any major issues. Another round soon, please! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
Recording why this was reverted in #9293, since the reason was never written down and it came up again when we looked at re-landing it. The notice is fine in itself. The problem is where it renders. Sonner puts it top right at 356x235, and that is where the Model hub keeps its own controls, so for the 8 seconds the toast is up those controls sit underneath it and cannot be clicked. Measured on two isolated installs built from this PR's merge base Blocked on downloads 2 and 3: Download 2, base on the left and head on the right. The filter row, the sort dropdown, the two icon buttons and the RAM and CPU chips are all present on the left and hidden on the right: Download 4, after Two things worth ruling out for anyone re-landing this, because both look plausible and both are wrong. The download progress card is not affected: it is bottom right at y=863 while the toast is top right at y=12, and the measured overlap is 0. The transport pills are not affected either: they sit at x=737 to 861 and the toast starts at x=1132, and the pill hit-tests to itself on every download. Only the controls listed above are actually covered. Worth noting that the notice ends with "go to 'Model Hub' and switch transport to HTTP", so the advice arrives at the same moment as a toast that covers part of the toolbar the user is being sent to.
If this is re-landed, the fix is placement rather than content. Rendering the notice inside the download panel it describes, or anywhere that is not on top of the hub toolbar, keeps the explanation without taking the controls away for 8 seconds at a time. |
…lbar (#9658) * Reapply "Say why a Xet download sits at 0% until it finishes (#9159)" (#9293) This reverts commit e326033. * Shrink the Xet notice so it clears the hub toolbar The notice itself was fine. Its size was not: 62 characters of title and 330 of description rendered 235px tall in the top-right corner, which is where the Model hub keeps its own toolbar. While the toast was up the capability filter, the sort dropdown, the Models and Datasets tabs and the repo action icons sat underneath it. Hit testing each control's own centre point put 4 to 6 of them inside the toast, so they could not be clicked, three times per install at 8s each. That is what #9293 reverted. Title is now 19 characters and the description 149, in plain language and one paragraph, which drops the pre-line class the old blank line needed. The character budget is asserted in the tests rather than left as a convention, since the failure is invisible to unit tests and to a screenshot taken at the wrong viewport. * Drop the HTTP hint: it left a 0.5px margin, not a margin The measured pair showed the shortened toast clearing the toolbar, but only just. At 149 characters it rendered 114.5px tall, bottom edge at y=126.5, against a hub filter row whose centre sits at y=127. Every control hit-tested as clickable, so the check passed, by half a pixel. A longer translation, a different font stack or a zoom level would have put it back over the row and re-broken what #9293 reverted. At 101 characters the toast ends near y=100 and does not reach the row at all, so the result stops depending on sub-pixel layout. The budget in the tests drops from 170 to 110, which now rejects the 149-char version rather than accepting it. The transport control is two clicks away in Model Hub and discoverable without being told. A toast that eats the toolbar is not worth it.



Problem
Xet is the most common download complaint we get, and the complaint is usually wrong: the download is fine. Xet fetches a model as parallel chunks and commits them in batches, and progress is read from the bytes allocated on disk, so a healthy Xet transfer reads 0% for a minute and then completes in one jump. From the outside that is indistinguishable from a hang, so people cancel a download that was working.
Change
The first three model downloads that start on Xet now explain it:
Details worth knowing:
localStoragewith an in-memory carry, so a browser that refuses the write (private mode, quota) does not turn this into a toast on every download.Testing
studio/frontend/tests/xet-progress-notice.test.tscovers the gate (Xet and models only), the three-download limit, the stored count across sessions, junk stored values, and the unwritable-storage carry.tsc -bclean,eslintandbiomeclean on the touched files, andvite buildsucceeds.