Skip to content

REST API: Move sideload metadata writing to the finalize endpoint (backport GB #75888)#48

Open
adamsilverstein wants to merge 3 commits into
reintroduce-client-side-mediafrom
backport/75888-sideload-finalize
Open

REST API: Move sideload metadata writing to the finalize endpoint (backport GB #75888)#48
adamsilverstein wants to merge 3 commits into
reintroduce-client-side-mediafrom
backport/75888-sideload-finalize

Conversation

@adamsilverstein
Copy link
Copy Markdown
Owner

@adamsilverstein adamsilverstein commented May 22, 2026

What

Core backport of Gutenberg #75888 — Upload Media: Enable concurrent sideload uploads.

Stacked on top of the client-side-media restore branch (reintroduce-client-side-media, #11324). Once the restore lands on trunk, this rebases onto trunk.

Why

Concurrent sideloads for the same attachment each did a read-modify-write of _wp_attachment_metadata, so parallel requests could overwrite each other's changes. The merged Gutenberg PR explored MySQL advisory locks and transient locks, then settled on removing the shared write entirely.

How

  • sideload_item() no longer writes attachment metadata. It returns lightweight sub-size data (image_size, dimensions, file, mime_type, filesize, and original_image for the scaled case). The scaled flow still repoints _wp_attached_file (that is not the contended _wp_attachment_metadata).
  • finalize_item() accepts a new sub_sizes array param (schema-validated) and applies all collected sub-sizes to the metadata in a single wp_update_attachment_metadata() before firing wp_generate_attachment_metadata.

This matches how core generates sub-sizes (one metadata write after all sizes exist).

Notes

  • The JS counterpart (media-utils sideloadToServer returning sub-size data; client-side accumulation passed to finalize) ships via the normal Gutenberg → Core package sync and is not part of this PHP backport.
  • Tests: updated test_sideload_scaled_image to assert the new response shape + finalize write, and added three finalize tests — test_finalize_writes_regular_sub_sizes, test_finalize_writes_original_metadata (covers the original branch), and test_finalize_preserves_image_meta (EXIF image_meta is preserved when finalize adds sub-sizes). Together with the existing test_finalize_item* tests, all three finalize branches (regular / scaled / original) plus the empty-sub_sizes path are covered. Validated locally with php -l and PHPCS (WordPress-Core); the full PHPUnit suite was not run locally (the wordpress-develop test env is not currently provisioned, and the suite does not run in CI on fork PRs to a non-default base branch).

Part of the post-restore client-side-media backport stack.


Trac ticket: https://core.trac.wordpress.org/ticket/65329

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 22, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4b8a6c55-9257-42b7-9a48-996faccfe4a0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch backport/75888-sideload-finalize

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 and usage tips.

Backport of Gutenberg PR #75888. Eliminate the read-modify-write race
between concurrent sideloads for the same attachment by no longer
writing attachment metadata in the sideload endpoint. Instead, sideload
returns lightweight sub-size data (dimensions, filename, filesize) which
the client accumulates and passes to the finalize endpoint, which writes
all collected sub-sizes in a single metadata update.

This matches how core generates sub-sizes (one metadata write after all
sizes exist) and replaces the earlier per-attachment locking approach
that the merged Gutenberg PR ultimately abandoned.
The three sub-size finalize tests added in this backport used the
placeholder ticket 62243 (the original client-side media feature ticket)
before a dedicated ticket existed. Trac #65329 now tracks this change, so
update those @ticket annotations. Pre-existing finalize tests keep 62243.
This backport changes the scaled-image sideload behavior (sideload now
returns sub-size data and metadata is written at finalize), so add a
65329 ticket reference alongside the existing 64737.
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