fix: download-crash-large-files#67
Conversation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
response.bytes() buffered the whole file in memory; >5GB downloads exhausted RAM and hung. Stream via bytes_stream() to a file in constant memory and log progress every 10%. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Log response status/content-length/content-encoding/transfer-encoding to explain
missing Content-Length ('unknown size'). Report exact byte count with human units
(KB/B) instead of flooring sub-1MB downloads to '0 MB', and warn on empty body.
Remove percent/byte progress logging and its unit tests per request. Keep the core fix: stream the response to disk in constant memory instead of buffering the whole file in RAM. Retain exact byte-count log and empty-body warning.
Storage URLs often return no Content-Length, so progress showed 'unknown size'. Thread RestoreInfo.size (bytes) through dispatch -> execute_restore -> download_backup, parse it, and log progress every 10% against that total.
Server sends size as a JSON integer (e.g. 1142), but the field was typed Option<String>, breaking status deserialization (ping_server task errored: 'invalid type: integer, expected a string'). Reuse string_or_number_to_string so both forms parse; downstream still gets Option<String>.
human_size rounding collapsed small downloads to '1 KB / 1 KB' for every milestone. Log exact byte counts instead: 'NN% (downloaded / total bytes)'.
Small files arrive in one chunk, so the while-loop logged all ten milestones at once with identical byte counts. Log only the highest 10% milestone a chunk crosses; tiny downloads now emit a single 100% line, multi-chunk downloads are unchanged.
📝 WalkthroughWalkthroughRestore size is now deserialized from string-or-number inputs, passed through restore dispatch and execution, and used by the downloader to stream the backup to disk with progress and completion logging. ChangesRestore size propagation
Sequence Diagram(s)sequenceDiagram
participant Dispatch
participant ExecuteRestore
participant DownloadBackup
participant HttpResponse
Dispatch->>ExecuteRestore: pass expected_size from db.data.restore.size
ExecuteRestore->>DownloadBackup: forward expected_size
DownloadBackup->>HttpResponse: bytes_stream()
HttpResponse-->>DownloadBackup: response chunks
DownloadBackup->>DownloadBackup: write chunks, flush file, log progress
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/services/restore/downloader.rs`:
- Around line 32-34: The restore download path currently uses Client::new()
without an explicit timeout, so update the downloader logic in the restore
downloader to build the reqwest client with
Client::builder().timeout(Duration::from_secs(30)) before calling send(); follow
the same pattern used in src/services/api/client.rs, and make sure Duration is
imported in the downloader module if it is not already available.
- Around line 103-122: The download flow in restore/downloader.rs currently only
warns when `downloaded == 0` and still returns `Ok(path)`, so invalid archives
can slip into restore prep. Update the `download(...)` logic to validate the
final downloaded size against `expected_size` (or at minimum reject
zero-byte/truncated results) after `file.flush().await?`, and fail with an error
instead of returning the path when the size is invalid. Keep the change
localized around the `downloaded` check and the final `Ok(path)` return so the
restore pipeline can stop early on bad downloads.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 8be8cc51-0986-42d1-af14-1e9419e420b5
📒 Files selected for processing (4)
src/services/api/models/agent/status.rssrc/services/restore/dispatcher.rssrc/services/restore/downloader.rssrc/services/restore/executor.rs
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Summary by CodeRabbit
New Features
Bug Fixes