Skip to content

Backup: find a download in progress again after a reload - #53870

Merged
dhasilva merged 3 commits into
trunkfrom
jetpack-3007-backup-a-download-in-progress-is-lost-when-the-page-reloads
Oct 20, 2026
Merged

dhasilva merged 3 commits into
trunkfrom
jetpack-3007-backup-a-download-in-progress-is-lost-when-the-page-reloads

Conversation

@dhasilva

@dhasilva dhasilva commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Fixes JETPACK-3007

Proposed changes

The Download screen kept the download id only in React state, so reloading while WordPress.com built the archive dropped the reader back to the checklist. WordPress.com kept building it, but the dashboard could not find it again.

  • Find the download again after a reload. A new GET /jetpack/v4/backups/downloads bridge route reads WordPress.com's latest downloads, in the same shape as the status route plus rewind_id. Before showing the checklist, the screen reads it (shows "Checking for a download in progress…") and picks up this backup's download if it is still building (progress continues) or ready (link shows straight away).
  • Keep the checklist under a ready download, so the reader can still make a different archive. Otherwise a remembered download would be the only thing the screen offers until it expires.
  • Don't follow another backup's download (found while working on this; folded in rather than filed separately). While one download builds, WordPress.com answers every new request with that job, whichever backup it is of. The bridge used to pass it through, so asking for backup B while A built showed A's archive under B's download point. The bridge now answers 409 download_in_progress, and the screen says "Another download is being prepared for this site. Try again once it finishes." Best effort: the check needs WordPress.com to send back rewindId, which its reply does today. Without it, the bridge returns the download id as it did before.
  • Report an expired link as expired, not running. WordPress.com keeps validUntil after it withdraws the link, and its list still returns such downloads months later (seen on a dev site: a link that lapsed two months earlier). Read as running, a resume would have polled it forever.
  • A file selection does not look for a download. The list cannot say which files a ready archive holds. A reload while one is still building already resumes it, because WordPress.com hands the running job back when the screen asks again.

Known limit, same as the wpcom-backup panel in #53688: asking for the same backup with a different selection while one builds follows the running job, since the list does not carry the selection.

Changelog: one comment-only entry in packages/backup. The redesigned dashboard has not shipped yet, so the default-on entries from #53443 carry the user-facing text, as with #53790.

Related product discussion/links

Does this pull request change what data or activity we track or use?

No.

Testing instructions

On a connected site with a Backup plan and some backups, go to Jetpack › VaultPress Backup.

Reload while building

  1. Open a backup's Download. Leave only WordPress plugins checked (Site database alone can finish in a few seconds), then Generate download.
  2. While Preparing download… shows, reload.
  3. Expect "Checking for a download in progress…" for a moment, then the progress bar continuing. On trunk the checklist comes back.

Reload once ready
4. Wait for Your download is ready, then reload.
5. Expect the link and its expiry, with the checklist below. Generate download from there starts a new one.

Another backup's download
6. Start a download of one backup. While it builds, open a different backup's Download and press Generate download.
7. Expect "Could not prepare the download" with "Another download is being prepared for this site. Try again once it finishes." and the code download_in_progress. On trunk the screen shows the first backup's progress and archive under the second backup's download point.

Unchanged paths
8. From the file browser, select files and choose Download: it starts on its own, as before.
9. A backup with no download under way shows the checklist after the brief check.

The route can also be read directly: GET /wp-json/jetpack/v4/backups/downloads (with a REST nonce) returns a list of { id, rewind_id, status, progress, url, valid_until, error }.

🤖 Generated with Claude Code

dhasilva and others added 2 commits October 20, 2026 13:55
The Download screen kept the download id only in React state, so a reload
while WordPress.com built the archive dropped back to the checklist. The
screen now reads the site's latest downloads first, through a new
/backups/downloads bridge route, and picks up this backup's download if it
is still building or ready.

While one download builds, WordPress.com answers every new request with that
job, whichever backup it is of. The bridge now refuses that reply with a 409
instead of letting the screen follow another backup's archive.

An expired link is reported as expired rather than running.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack), and enable the jetpack-3007-backup-a-download-in-progress-is-lost-when-the-page-reloads branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack jetpack-3007-backup-a-download-in-progress-is-lost-when-the-page-reloads

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@github-actions

Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!

@jp-launch-control

jp-launch-control Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Code Coverage Summary

Coverage changed in 5 files.

File Coverage Δ% Δ Uncovered
projects/packages/backup/src/dashboard/data/api/download.ts 12/13 (92.31%) 4.81% 0 💚
projects/packages/backup/src/dashboard/data/query-client.ts 26/26 (100.00%) 0.00% 0 💚
projects/packages/backup/src/dashboard/hooks/use-download.ts 62/62 (100.00%) 0.00% 0 💚
projects/packages/backup/src/dashboard/screens/download.tsx 41/41 (100.00%) 0.00% 0 💚
projects/packages/backup/src/rest/class-download-bridge.php 208/215 (96.74%) 0.99% 0 💚

Full summary · PHP report · JS report

@CGastrell

Copy link
Copy Markdown
Contributor

Thanks for this, @dhasilva. The diff looks good. I found no blockers. I read the code only and did not run the tests locally.

Verdict: Minor issues. It can merge after you look at the points below.

Suggestions (none verified by a run, so these are ideas only):

  1. If the downloads lookup fails, the screen shows "Checking for a download in progress…" for longer than needed, because the query client retries once (retry: 1). Maybe set retry: false on this query, since the form is the fallback anyway.
  2. get_downloads() returns a 500 when WordPress.com's body is not a list. If WordPress.com sends {} or null for a site with no downloads, that is a normal state and not an error. Can you confirm what the empty case looks like?
  3. The 409 download_in_progress check only runs when WordPress.com echoes rewindId. If the key is missing, the old behavior returns. This is fine as best effort. Maybe say so in the description.
  4. In download-file-selection.test.tsx, the loosened status assertion also passes when there are no other regions, because the loop body never runs. A count check would keep it strict.

CI: the only failing check is the code coverage requirement. Please add a test for the uncovered lines, or use the Covered by non-unit tests label with a note.

Next step: we are testing this manually now, starting with the reload-while-building flow and the other-backup 409 flow (steps 1–3 and 6–7). I will report back here.

Terminator

A failed lookup now offers the form at once instead of after the query
client's retry, since a new request is handed any download still building.
The read-route failure tests cover the list route as rows, the newest of
several downloads is tested, and the live-region test requires the one hint.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@dhasilva

Copy link
Copy Markdown
Contributor Author

@CGastrell Pushed d251cae.

  1. Done: the downloads lookup has retry: false. Starting a new download hands back any download still building, or gets the 409, so the form is a safe fallback. The lookup-failure test now runs with production's one retry and expects the form without waiting for it.
  2. The empty case is []. WordPress.com builds this list by mapping over the site's download records, so it is always a JSON list, and failures come back as a non-200. Calypso relies on the same shape when it takes the first item. The 500 only covers a 200 whose body is not a list, and the screen treats any lookup failure as nothing to resume and shows the checklist, so a reader never sees it.
  3. Agreed, it's best effort. WordPress.com's create reply is the same formatted download as the list, rewindId included, and the 409 fired when I tested it live. Noted in the description.
  4. Done: it now expects exactly one other region, the hint, and that it is empty.

Coverage: the list route's network and non-200 failures now run as data-provider rows on the status route's tests, and picking the newest of several downloads has a test (reversing the sort fails it). is_same_backup() is one expression now. The line still uncovered is the missing-blog-id guard, which no bridge's tests cover.

Generated by Claude.

@dhasilva
dhasilva merged commit 762a62a into trunk Oct 20, 2026
106 of 107 checks passed
@dhasilva
dhasilva deleted the jetpack-3007-backup-a-download-in-progress-is-lost-when-the-page-reloads branch October 20, 2026 19:12
@github-actions github-actions Bot added [Status] UI Changes Add this to PRs that change the UI so documentation can be updated. and removed [Status] Needs Review This PR is ready for review. labels Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Backup [Status] UI Changes Add this to PRs that change the UI so documentation can be updated. [Tests] Includes Tests [Type] Bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants