Skip to content

fix: download-crash-large-files#67

Merged
RambokDev merged 9 commits into
mainfrom
fix/download-crash-large-files
Jun 25, 2026
Merged

fix: download-crash-large-files#67
RambokDev merged 9 commits into
mainfrom
fix/download-crash-large-files

Conversation

@RambokDev

@RambokDev RambokDev commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Restore downloads now show progress updates during large file transfers when the expected size is known.
    • Restore operations now use expected file size information to improve download handling.
  • Bug Fixes

    • Improved handling of restore size values when they arrive as either text or numbers.
    • Added a warning when a backup download completes with no data, making failed transfers easier to spot.

RambokDev and others added 9 commits June 25, 2026 11:14
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.
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Restore 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.

Changes

Restore size propagation

Layer / File(s) Summary
RestoreInfo size deserialization
src/services/api/models/agent/status.rs
RestoreInfo.size now deserializes with string_or_number_to_string and defaults when missing.
Restore size wiring
src/services/restore/dispatcher.rs, src/services/restore/executor.rs
dispatch reads db.data.restore.size, execute_restore accepts expected_size, and the value is forwarded into download_backup.
Streaming backup download
src/services/restore/downloader.rs
download_backup accepts expected_size, streams response chunks to disk, and logs progress, duration, and empty-download warnings.

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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Portabase/agent#22: Introduces the restore pipeline changes that this PR extends with expected_size propagation and download streaming.

Poem

🐰 I sniffed a size both big and small,
A number or a string can hop in all.
Then bytes went streaming, line by line,
And progress lights began to shine.
Hoppity-ho, the backup's fine! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: fixing large-file download crashes by improving restore download handling.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/download-crash-large-files

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between ea010ce and 247ddb6.

📒 Files selected for processing (4)
  • src/services/api/models/agent/status.rs
  • src/services/restore/dispatcher.rs
  • src/services/restore/downloader.rs
  • src/services/restore/executor.rs

Comment thread src/services/restore/downloader.rs
Comment thread src/services/restore/downloader.rs
@codecov

codecov Bot commented Jun 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 75 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/services/restore/downloader.rs 0.00% 62 Missing ⚠️
src/services/restore/executor.rs 0.00% 9 Missing ⚠️
src/services/restore/dispatcher.rs 0.00% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

@RambokDev RambokDev merged commit 038c552 into main Jun 25, 2026
2 of 3 checks passed
@RambokDev RambokDev deleted the fix/download-crash-large-files branch June 25, 2026 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant