Skip to content

Add PutMultipartOptions::mode for conditional multipart completion - #863

Open
chromafish wants to merge 1 commit into
apache:mainfrom
chromafish:conditional-multipart-put
Open

chromafish wants to merge 1 commit into
apache:mainfrom
chromafish:conditional-multipart-put

Conversation

@chromafish

Copy link
Copy Markdown

Closes #289

This adds support for S3 and InMemory only. GCS, Azure and LocalFileSystem return NotImplemented. Azure's Put Block List accepts If-None-Match: *, so it could be implemented, but I'm not very familiar with Azure Blob Storage. I can take a shot at it if it's wanted.

Rationale for this change

Multipart uploads are currently always unconditional overwrites. S3 supports If-None-Match: * on CompleteMultipartUpload, and the S3 client already sends it internally for S3CopyIfNotExists::Multipart. It just isn't exposed through the public multipart API.

What changes are included in this PR?

  • PutMultipartOptions gains a mode field, allowing multipart uploads to use PutMode::Create.
  • AmazonS3::put_multipart_opts resolves the mode the same way put_opts does. On completion, it uses the same error handling as put_opts, which I extracted into a map_create_error function.
  • MultipartStore::create_multipart_opts returns NotSupported for any mode other than Overwrite (see limitations below).
  • complete_multipart no longer marks Create completions as idempotent, so they aren't retried on timeout, matching put_opts with Create. This is to avoid the scenario where the first attempt succeeded but its response was lost, so the retry would fail its If-None-Match and report the caller's own write as AlreadyExists. This also applies to the existing copy_if_not_exists with S3CopyIfNotExists::Multipart.

Limitations

  • mode only takes effect through ObjectStore::put_multipart_opts. MultipartStore uploads are stateless between create_multipart_opts and complete_multipart, and on S3 the condition is a header on CompleteMultipartUpload, so there's nowhere to carry the mode to completion. Supporting it would need MultipartStore::complete_multipart to accept the mode, e.g. through a new complete_multipart_opts method. I've left that out since it adds a new API surface to the trait, but I can follow up with this if you'd like.
  • PutMode::Update isn't supported for multipart uploads.

Are there any user-facing changes?

Yes. PutMultipartOptions has a new public field, so code that builds it with a
struct literal and no ..Default::default() will stop compiling.

put_opts supports PutMode::Create, but a multipart upload has no way to
complete as create-if-absent, so large immutable objects can't get the
same guarantee. S3 supports If-None-Match: * on CompleteMultipartUpload,
and the S3 client already sends it for S3CopyIfNotExists::Multipart.

PutMultipartOptions gains a `mode`, applied when the upload completes.
AmazonS3 completes a Create upload with If-None-Match: * (requiring
conditional put to be enabled, as put_opts does) and reports an existing
object as AlreadyExists. InMemory honors it too. LocalFileSystem, GCS and
Azure return NotImplemented from put_multipart_opts for any mode other
than Overwrite. Update isn't supported for multipart uploads.

MultipartStore::create_multipart_opts returns NotSupported for any mode
other than Overwrite: the upload is stateless between creation and
complete_multipart, so the mode couldn't be applied.

As with Create in put_opts, a Create completion is no longer marked
idempotent, so it isn't retried on timeout: if the first attempt
succeeded, the retry would fail its If-None-Match and report the caller's
own write as AlreadyExists. This also applies to copy_if_not_exists with
S3CopyIfNotExists::Multipart.

Adds a put_multipart_opts_create integration test, run for S3,
InMemory, LocalFileSystem, GCS and Azure.
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.

object_store: put_multipart_opts should allow setting PutMode

1 participant