fix: resumable update pause and phase-aware cancel#91
Merged
Conversation
Downloads now stage into a persistent, URL-keyed cache instead of a per-run staging dir, so the engine's `.part` resume survives a pause — pausing keeps the progress screen up with a 〔继续〕 that picks up from the byte it stopped at, and cancel discards the partial. The cancel button is danger-styled and usable through the preparing phase, while a finished download shows "正在安装,请勿关闭" instead of dead, unexplained buttons. Fixes the old behavior where pause dumped the user back to home and "再次更新会继续下载" never actually resumed. Backend: - staging: persistent download cache (FNV-1a key, toolchain-stable) + Result-returning clear; stale sweep prunes abandoned partials - mac/win: a drop-guarded abort latch (reset race-free on op exit, never at entry) makes the preparing phase cancellable; abort checkpoints sit before every destructive step and on the cache-hit path; perform/ install/stage each own the guard so a cancel can't leak to the next op - new mac_discard_download / win_discard_download commands clear a paused partial when the user cancels from the paused state Frontend: - paused state with resume + danger cancel + "finishing" install copy; discard wiring that only reports cancelled once the partial is gone - 4 new progress keys across all 11 locales; a pause glyph for the ring
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
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.
Why
The in-app update flow had four problems (reported from the macOS updater UI):
Root cause of (2): downloads staged into a per-run unique staging dir that
staging.discard()wiped on pause — so the engine's.partresume (curl -C -) could never find it, and pause/cancel were effectively identical.What changed
Backend
staging::download_cache_path, FNV-1a key for cross-toolchain stability) instead of a per-run dir, so a paused.partsurvives and the next run resumes from where it stopped. Success clears the cache; failure/pause keeps it; the stale sweep prunes abandoned partials.clear_download_cachenow returnsResultso a paused-state cancel only reports success once the partial is actually gone.AbortGuard/WinAbortGuard) makes the preparing phase cancellable. It resets the latch on op exit, never at entry — so a cancel racing the op's startup (the cancel command holds no op lock) isn't wiped, and the next op starts clean. Abort checkpoints sit before every destructive step and on the cache-hit path;perform/install/stageeach own the guard so a cancel can't leak into the next operation.mac_discard_download/win_discard_downloadcommands clear a paused partial when the user cancels from the paused state.Frontend (
Home.tsx+WinHome.tsx, symmetric)danger-styled and discards.pauseglyph for the ring.Verification
cargo clippy --workspace --all-targets -- -D warnings✅cargo test --workspace✅ (50 tests, incl. abort-guard race-free invariants for mac + win)npm run check/npm run test(41) /npm run build✅codex review --uncommitted, iterated to no comments (5 rounds — it surfaced a startup-window race, abort blind spots, latch residue across stage paths, and a cache-hit cancel window, all now closed).