Skip to content

Commit b90a261

Browse files
authored
feat: add Extensions to object store PutMultipartOpts (#7214)
1 parent 9384224 commit b90a261

File tree

5 files changed

+70
-6
lines changed

5 files changed

+70
-6
lines changed

object_store/src/aws/client.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,12 @@ impl S3Client {
633633
location: &Path,
634634
opts: PutMultipartOpts,
635635
) -> Result<MultipartId> {
636+
let PutMultipartOpts {
637+
tags,
638+
attributes,
639+
extensions,
640+
} = opts;
641+
636642
let mut request = self.request(Method::POST, location);
637643
if let Some(algorithm) = self.config.checksum {
638644
match algorithm {
@@ -644,8 +650,9 @@ impl S3Client {
644650
let response = request
645651
.query(&[("uploads", "")])
646652
.with_encryption_headers()
647-
.with_attributes(opts.attributes)
648-
.with_tags(opts.tags)
653+
.with_attributes(attributes)
654+
.with_tags(tags)
655+
.with_extensions(extensions)
649656
.idempotent(true)
650657
.send()
651658
.await?

object_store/src/azure/client.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,12 @@ impl AzureClient {
599599
parts: Vec<PartId>,
600600
opts: PutMultipartOpts,
601601
) -> Result<PutResult> {
602+
let PutMultipartOpts {
603+
tags,
604+
attributes,
605+
extensions,
606+
} = opts;
607+
602608
let blocks = parts
603609
.into_iter()
604610
.map(|part| BlockId::from(part.content_id))
@@ -607,8 +613,9 @@ impl AzureClient {
607613
let payload = BlockList { blocks }.to_xml().into();
608614
let response = self
609615
.put_request(path, payload)
610-
.with_attributes(opts.attributes)
611-
.with_tags(opts.tags)
616+
.with_attributes(attributes)
617+
.with_tags(tags)
618+
.with_extensions(extensions)
612619
.query(&[("comp", "blocklist")])
613620
.idempotent(true)
614621
.send()

object_store/src/buffered.rs

+17
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ pub struct BufWriter {
222222
max_concurrency: usize,
223223
attributes: Option<Attributes>,
224224
tags: Option<TagSet>,
225+
extensions: Option<::http::Extensions>,
225226
state: BufWriterState,
226227
store: Arc<dyn ObjectStore>,
227228
}
@@ -259,6 +260,7 @@ impl BufWriter {
259260
max_concurrency: 8,
260261
attributes: None,
261262
tags: None,
263+
extensions: None,
262264
state: BufWriterState::Buffer(path, PutPayloadMut::new()),
263265
}
264266
}
@@ -289,6 +291,19 @@ impl BufWriter {
289291
}
290292
}
291293

294+
/// Set the extensions of the uploaded object
295+
///
296+
/// Implementation-specific extensions. Intended for use by [`ObjectStore`] implementations
297+
/// that need to pass context-specific information (like tracing spans) via trait methods.
298+
///
299+
/// These extensions are ignored entirely by backends offered through this crate.
300+
pub fn with_extensions(self, extensions: ::http::Extensions) -> Self {
301+
Self {
302+
extensions: Some(extensions),
303+
..self
304+
}
305+
}
306+
292307
/// Write data to the writer in [`Bytes`].
293308
///
294309
/// Unlike [`AsyncWrite::poll_write`], `put` can write data without extra copying.
@@ -325,6 +340,7 @@ impl BufWriter {
325340
let opts = PutMultipartOpts {
326341
attributes: self.attributes.take().unwrap_or_default(),
327342
tags: self.tags.take().unwrap_or_default(),
343+
extensions: self.extensions.take().unwrap_or_default(),
328344
};
329345
let upload = self.store.put_multipart_opts(&path, opts).await?;
330346
let mut chunked =
@@ -384,6 +400,7 @@ impl AsyncWrite for BufWriter {
384400
let opts = PutMultipartOpts {
385401
attributes: self.attributes.take().unwrap_or_default(),
386402
tags: self.tags.take().unwrap_or_default(),
403+
extensions: self.extensions.take().unwrap_or_default(),
387404
};
388405
let store = Arc::clone(&self.store);
389406
self.state = BufWriterState::Prepare(Box::pin(async move {

object_store/src/gcp/client.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -453,9 +453,17 @@ impl GoogleCloudStorageClient {
453453
path: &Path,
454454
opts: PutMultipartOpts,
455455
) -> Result<MultipartId> {
456+
let PutMultipartOpts {
457+
// not supported by GCP
458+
tags: _,
459+
attributes,
460+
extensions,
461+
} = opts;
462+
456463
let response = self
457464
.request(Method::POST, path)
458-
.with_attributes(opts.attributes)
465+
.with_attributes(attributes)
466+
.with_extensions(extensions)
459467
.header(&CONTENT_LENGTH, "0")
460468
.query(&[("uploads", "")])
461469
.send()

object_store/src/lib.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -1223,7 +1223,7 @@ impl From<Attributes> for PutOptions {
12231223
}
12241224

12251225
/// Options for [`ObjectStore::put_multipart_opts`]
1226-
#[derive(Debug, Clone, PartialEq, Eq, Default)]
1226+
#[derive(Debug, Clone, Default)]
12271227
pub struct PutMultipartOpts {
12281228
/// Provide a [`TagSet`] for this object
12291229
///
@@ -1233,8 +1233,33 @@ pub struct PutMultipartOpts {
12331233
///
12341234
/// Implementations that don't support an attribute should return an error
12351235
pub attributes: Attributes,
1236+
/// Implementation-specific extensions. Intended for use by [`ObjectStore`] implementations
1237+
/// that need to pass context-specific information (like tracing spans) via trait methods.
1238+
///
1239+
/// These extensions are ignored entirely by backends offered through this crate.
1240+
///
1241+
/// They are also eclused from [`PartialEq`] and [`Eq`].
1242+
pub extensions: ::http::Extensions,
1243+
}
1244+
1245+
impl PartialEq<Self> for PutMultipartOpts {
1246+
fn eq(&self, other: &Self) -> bool {
1247+
let Self {
1248+
tags,
1249+
attributes,
1250+
extensions: _,
1251+
} = self;
1252+
let Self {
1253+
tags: other_tags,
1254+
attributes: other_attributes,
1255+
extensions: _,
1256+
} = other;
1257+
(tags == other_tags) && (attributes == other_attributes)
1258+
}
12361259
}
12371260

1261+
impl Eq for PutMultipartOpts {}
1262+
12381263
impl From<TagSet> for PutMultipartOpts {
12391264
fn from(tags: TagSet) -> Self {
12401265
Self {

0 commit comments

Comments
 (0)