Repository navigation
Download control: sizes and speed, ids and cancel, pause and resume - #17
Merged
Merged
Conversation
…bytes download takes optional received:, total: and speed: bindings next to progress: and status:. The fields a download can bind are one table, DownloadField in nifty-runtime, which the checker, the interpreter, the compiled runtime and codegen all read; a report says which fields it writes, so each runner applies it the same way. Progress is reported at most every 100 ms, with the speed averaged over the last two seconds. format_bytes(n) is the first built-in that gives a value; it only reads, so the UI may call it. Sizes use units of 1000, as macOS and browsers do. Compiled apps now pass a download as one DownloadDesc with a list of bindings, so ABI_VERSION goes to 3.
download takes id: $string, and writes a process-wide unique id such as download-3 into it. cancel_download(id) stops that download and removes its partial file; status becomes Cancelled. A download reporting into a list item must bind id: in that item. Before each report and after each action, the runtime finds the item holding the id and moves the bindings that share its path, so removing or rebuilding rows no longer sends reports to the wrong row; a download whose item is gone is cancelled. The search is shared by the interpreter and compiled apps through nifty-download's StateReader. Each download now runs as a coordinator thread that handles one ordered stream of events: its connection's progress and the app's commands. The connection does the blocking network reads and writes the file through an Outlet the coordinator can close at any time, so cancelling never waits on the network. Dropping Downloads, as nf dev does on reload, stops every download and removes its partial file before returning. The test server serves many requests and can stall mid-body until the test resumes it, so tests cancel and reorder rows without sleeping. Also drops the roadmap's in-progress entry for #16, now merged, and pins the Zed grammar to 7f40a5b. ABI_VERSION goes to 4.
pause_download(id) closes the download's connection and keeps its partial file; status becomes Paused. resume_download(id) opens a new connection asking for the rest with Range: bytes=N-. A server that answers 206 with a Content-Range continues from there; one that ignores the range sends the whole file, and the download starts over from zero. A 206 without a Content-Range fails rather than guessing. A download now writes to name.part and takes its final name, the first free one from its copy number on, once saved, so a file left behind when macOS ends the app mid-download reads as unfinished. Each connection's events carry its id, and the outlet counts what it wrote, so a pause knows exactly what is on disk even with events from the old connection still queued. The test server answers range requests unless told not to.
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The first half of download control: sizes and speed, a download id that follows its list item, cancel, and pause and resume. Each feature reaches the checker, interpreter, compiled apps, the runtime, the LSP, the highlighters, the reference docs,
fixtures/downloader.nfand the roadmap. Several connections per file, choosing the file name, and headers and retries come in a follow-up.What's in it
1. Bytes, size and speed (e72d2ed)
download(url, to:, progress: $p, status: $s, received: $r, total: $t, speed: $v).received,totalandspeedare optionalintbindings.totalis0until the server gives the size. It is set to the file's size once the file is saved.speedis in bytes per second, averaged over the last 2 seconds. The bindings update at most 10 times a second.format_bytes(n) -> string, for example1.5 KB. It counts in 1000s, like macOS and browsers. It only reads, so the UI can call it.DownloadFieldinnifty-runtime. The checker, interpreter, compiled runtime and codegen all read it. Compiled apps pass oneDownloadDesc.2. Download ids and cancel (c67ec14)
download(…, id: $items[last].id)writes an id such asdownload-3.cancel_download(id)stops the download, removes the partial file and setsstatustoCancelled.id:is required whenever a download writes into a list item. This is syntax decision row 24.nf devreload stops every download and removes its partial file before the new program starts.3. Pause and resume (476fe9f)
pause_download(id)keeps the partial file and setsstatustoPaused.resume_download(id)sendsRange: bytes=N-.Content-Rangecontinues from there.Content-Rangefails rather than guessing.name.partand renamed to the first free final name once saved, so a leftover file is clearly unfinished.The compiled app interface (
ABI_VERSION) is now 4.Design decisions to review
string, not a handle type.nf devreload stops downloads rather than carrying them into the new program..partfiles behind, because AppKit quits withexit(). Fixing it needs an on-quit hook in both backends.name.partuntil saved.totalis0when the size is unknown, rather than a special value.format_bytescounts in 1000s. Windows Explorer counts in 1024s; the docs say so.statusto the literal strings"Downloading…"and"Paused". Enums would make this cleaner.Checked
make checkpasses: fmt, clippy (-D warnings) on macOS and with--target x86_64-pc-windows-msvc, build,cargo test --workspace, the tree-sitter corpus (32/32) and the VS Code grammar test.Content-Lengthrange: bytes=4-fixtures/downloader.nf.Not yet checked by hand
macOS:
fixtures/downloader.nf. Check the sizes and speed it shows.Windows:
fixtures/downloader.nf..partfile open..partfiles are removed when the app quits..partfile over the placeholder when a download is saved, including when a file with that name appeared during the download.Follow-ups
docs/src/guide/bindings.mdstill says onlytext_fieldandcheckboxtake bindings.