Skip to content

v0.7.0

Choose a tag to compare

@obakeng-develops obakeng-develops released this 02 Sep 10:42
· 39 commits to main since this release
72707cd

A delivery can now be larger than one upload request.

Multipart direct upload

ActiveStorage::Service::S3Service#url_for_direct_upload issues exactly one presigned PUT, and S3 and R2 both refuse a single PUT above 4.995 GiB. That was the real ceiling on a delivery, on every plan and every self-hosted install, and no configuration moved it. multipart_upload_threshold looks like the fix and is not: it applies only to server-side uploads, which the direct upload path never takes.

A file over 100 MB now uploads in parts. The browser asks for a window of presigned part URLs, sends the parts itself, and tells the server when to assemble them. Whatever Campsend::Policy#max_send_size_for returns is now the only ceiling you have.

This needs an S3-compatible bucket. Disk storage still sends one request per file and still stops around 5 GB.

Your bucket needs one CORS line

"ExposeHeaders": ["ETag"] is no longer decorative. Each part upload returns an ETag that the browser has to read and send back, so without that rule an upload fails at the last step, after every byte has already gone over the wire. The self-hosting docs have carried this rule from the start; now it matters.

Abandoned uploads clean themselves up

An upload a browser starts and never finishes leaves its parts in the bucket, and no storage provider removes them on its own. SecurityCleanupJob now aborts anything still in flight after a day, before it purges the blob that reserved it. It is already scheduled daily, so there is nothing to add.

There is no new table. The upload id travels to the browser in a signed token and comes back on every call, and reconciliation asks the bucket what is in flight rather than keeping a second copy that can disagree with it.

Uploads that lie about their size are thrown away

A reservation trusts a client-supplied byte count. With one PUT that is self-limiting. With multipart it is not, so a client could reserve a megabyte and send ten gigabytes past the storage limit. Completion measures the assembled object and purges it if it does not match what was reserved.

The composer says what it means

It used to say "2 GB total", which reads as an account total rather than a per-delivery limit. It now says "per delivery", and a distribution that meters storage can report usage beside it through the new Campsend::Policy#storage_usage_for, which returns nil here.

Also

config/environments/development.rb reads ACTIVE_STORAGE_SERVICE the way production.rb already did, so you can point development at a real bucket.

Minor rather than patch: three new endpoints, a new model, and two new policy methods. Nothing changes for an install that only ever uploads small files.

Full changelog: v0.6.0...v0.7.0