Skip to content

feat(rust-client): Add Multipart Upload API#468

Merged
lcian merged 33 commits into
mainfrom
lcian/feat/multipart-upload-rust-client
May 29, 2026
Merged

feat(rust-client): Add Multipart Upload API#468
lcian merged 33 commits into
mainfrom
lcian/feat/multipart-upload-rust-client

Conversation

@lcian
Copy link
Copy Markdown
Member

@lcian lcian commented May 8, 2026

⚠️ Stacked on #463

Implements a multipart upload API for the Rust client.
Instead of going for a low-level API where calls match exactly HTTP calls as I've planned initially, I've decided to abstract some things, for example, initiating a multipart upload returns a MultipartUpload that represents it, much like the existing Session we have.
Please look at the README to see the intended usage.

Also makes a couple changes that aren't strictly related to the multipart upload impl:

  • Moves multipart upload-related types from objectstore-server to objectstore-types, to make them usable from the client too, given that they both deal with the wire format.
  • Makes the server return a vec of completed parts, each with their own part_number when calling ListParts, as opposed to a BTreeMap.
  • Makes Usecase::compression take an Option<Compression>. This is a breaking change that makes it possible to disable default-compression on a usecase, which wasn't possible before.

Close FS-357

@lcian lcian changed the base branch from main to lcian/feat/multipart-upload-endpoints May 8, 2026 16:09
@codecov
Copy link
Copy Markdown

codecov Bot commented May 8, 2026

Codecov Report

❌ Patch coverage is 77.14286% with 72 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.56%. Comparing base (b84e11f) to head (bb111e4).

Files with missing lines Patch % Lines
clients/rust/src/multipart.rs 71.09% 61 Missing ⚠️
objectstore-types/src/multipart.rs 74.19% 8 Missing ⚠️
objectstore-server/src/endpoints/common.rs 0.00% 1 Missing ⚠️
objectstore-service/src/backend/tiered.rs 66.66% 1 Missing ⚠️
objectstore-service/src/error.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #468      +/-   ##
==========================================
- Coverage   87.76%   87.56%   -0.21%     
==========================================
  Files          80       81       +1     
  Lines       12621    12896     +275     
==========================================
+ Hits        11077    11292     +215     
- Misses       1544     1604      +60     
Components Coverage Δ
Rust Backend 92.33% <73.80%> (-0.06%) ⬇️
Rust Client 79.70% <77.65%> (-0.08%) ⬇️
Python Client 86.36% <ø> (ø)

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@lcian

This comment was marked as outdated.

@lcian

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

@lcian

This comment was marked as spam.

@lcian

This comment was marked as spam.

@lcian lcian changed the title lcian/feat/multipart upload rust client feat(rust-client): Add Multipart Upload API May 11, 2026
Comment thread clients/rust/src/multipart.rs
Comment thread clients/rust/src/multipart.rs
@lcian lcian marked this pull request as ready for review May 11, 2026 13:10
@lcian lcian requested a review from a team as a code owner May 11, 2026 13:10
@linear-code

This comment was marked as spam.

@lcian lcian marked this pull request as draft May 12, 2026 14:25
@lcian lcian marked this pull request as ready for review May 12, 2026 14:27
cursor[bot]

This comment was marked as outdated.

@lcian lcian requested a review from matt-codecov May 15, 2026 16:37
@lcian lcian force-pushed the lcian/feat/multipart-upload-endpoints branch from 5babbfb to c33ba6f Compare May 15, 2026 16:57
@lcian lcian force-pushed the lcian/feat/multipart-upload-rust-client branch from 93557e1 to 84181ed Compare May 15, 2026 17:01
Copy link
Copy Markdown
Contributor

@matt-codecov matt-codecov left a comment

Choose a reason for hiding this comment

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

ran out of steam before i could finish reviewing, sorry

Comment thread clients/rust/src/get.rs
Comment thread clients/rust/src/multipart.rs
Comment thread clients/rust/src/multipart.rs
Comment thread clients/rust/src/multipart.rs
@matt-codecov matt-codecov self-requested a review May 22, 2026 01:27
Copy link
Copy Markdown
Contributor

@matt-codecov matt-codecov left a comment

Choose a reason for hiding this comment

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

accept w comments (including my comments last week)

Comment thread clients/rust/src/multipart.rs
@lcian lcian force-pushed the lcian/feat/multipart-upload-endpoints branch from ab5d578 to a2496b3 Compare May 29, 2026 08:20
Base automatically changed from lcian/feat/multipart-upload-endpoints to main May 29, 2026 09:28
lcian and others added 19 commits May 29, 2026 11:50
The test was inheriting the usecase default (zstd) compression but
uploading raw uncompressed parts, causing "Unknown frame descriptor"
on read-back.
Instead of disabling compression, send properly zstd-compressed parts
so the test exercises the multiple_members concatenated-frame
decompression path that the client uses for multipart objects.
Allow callers to disable compression at the Usecase level by passing
None to with_compression(). Previously the method only accepted a
Compression value, making it impossible to set "no compression" as
the usecase-wide default.

The internal field and compression() accessor are now Option<Compression>.
The default remains Compression::Zstd. Per-operation builders are
unaffected since they already accepted Option<Compression>.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… test

The full_upload_uncompressed test was sending zstd-compressed parts
while the upload metadata had compression=None, so GET returned the
raw compressed bytes instead of the expected plaintext.
@lcian lcian force-pushed the lcian/feat/multipart-upload-rust-client branch from 3565150 to b1e6a42 Compare May 29, 2026 09:51
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b1e6a42. Configure here.

Comment thread objectstore-server/src/endpoints/multipart.rs
lcian added 5 commits May 29, 2026 11:57
These were carried over from the old base branch during the restack
and downgraded several Python dependencies.
Moves the validated `UploadId` newtype and `PartNumber` (`NonZeroU32`)
type alias from `objectstore-service` to `objectstore-types` so they
can be shared between the server and Rust client. Updates all wire
format types to use the stricter types, removing the need for
conversions at the server endpoint boundary.
The client methods (put, put_stream, put_read, resume_multipart_upload)
accept u32 for part numbers and String for upload IDs, converting to the
stricter internal types (PartNumber, UploadId) at the boundary. This
keeps the public API simple while maintaining type safety internally.
Replace InvalidArgument with InvalidPartNumber and InvalidUploadId.
Previously fell through to the catch-all 500 Internal Server Error.
@lcian lcian merged commit 8e5faf7 into main May 29, 2026
25 checks passed
@lcian lcian deleted the lcian/feat/multipart-upload-rust-client branch May 29, 2026 11:04
lcian added a commit that referenced this pull request May 29, 2026
⚠️ Stacked on #468

Adds an optional `multipart` config block for stresstest workloads that
exercises the new multipart uploads feature.
When enabled, writes for objects >1 KiB use multipart uploads with the
configured part size and concurrency.

This can be used in both `weighted` and `throughput` mode, but not in
`batch` mode, as that wouldn't make any sense.

Also adds a `README.md` that documents the meaning of all stresstest
options and when they can/should be used.

Part of FS-343

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
lcian added a commit that referenced this pull request May 29, 2026
⚠️ Stacked on #468

Adds a Multipart Upload API to the Python client.
The API is basically the same as the one implemented in
#468 for the Rust client.

Close FS-340
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.

2 participants