From f954bc1fa7a30a179cf18d73db192da4f5e92107 Mon Sep 17 00:00:00 2001 From: Raphael Taylor-Davies Date: Thu, 30 Jan 2025 09:59:47 +0000 Subject: [PATCH 1/2] Add test of out of order UploadPart --- object_store/src/aws/mod.rs | 1 + object_store/src/azure/mod.rs | 1 + object_store/src/gcp/mod.rs | 1 + object_store/src/integration.rs | 34 +++++++++++++++++++++++++++++++-- 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/object_store/src/aws/mod.rs b/object_store/src/aws/mod.rs index 82ef909de984..b065927b6486 100644 --- a/object_store/src/aws/mod.rs +++ b/object_store/src/aws/mod.rs @@ -571,6 +571,7 @@ mod tests { stream_get(&integration).await; multipart(&integration, &integration).await; multipart_race_condition(&integration, true).await; + multipart_out_of_order(&integration).await; signing(&integration).await; s3_encryption(&integration).await; put_get_attributes(&integration).await; diff --git a/object_store/src/azure/mod.rs b/object_store/src/azure/mod.rs index ea4dd8f567a9..bbecba57177a 100644 --- a/object_store/src/azure/mod.rs +++ b/object_store/src/azure/mod.rs @@ -314,6 +314,7 @@ mod tests { put_opts(&integration, true).await; multipart(&integration, &integration).await; multipart_race_condition(&integration, false).await; + multipart_out_of_order(&integration).await; signing(&integration).await; let validate = !integration.client.config().disable_tagging; diff --git a/object_store/src/gcp/mod.rs b/object_store/src/gcp/mod.rs index a2f512415a8d..2aa99765d9da 100644 --- a/object_store/src/gcp/mod.rs +++ b/object_store/src/gcp/mod.rs @@ -298,6 +298,7 @@ mod test { stream_get(&integration).await; multipart(&integration, &integration).await; multipart_race_condition(&integration, true).await; + multipart_out_of_order(&integration).await; // Fake GCS server doesn't currently honor preconditions get_opts(&integration).await; put_opts(&integration, true).await; diff --git a/object_store/src/integration.rs b/object_store/src/integration.rs index 25a929459ef9..1d082d1a7c9d 100644 --- a/object_store/src/integration.rs +++ b/object_store/src/integration.rs @@ -29,8 +29,8 @@ use core::str; use crate::multipart::MultipartStore; use crate::path::Path; use crate::{ - Attribute, Attributes, DynObjectStore, Error, GetOptions, GetRange, ObjectStore, PutMode, - PutPayload, UpdateVersion, WriteMultipart, + Attribute, Attributes, DynObjectStore, Error, GetOptions, GetRange, MultipartUpload, + ObjectStore, PutMode, PutPayload, UpdateVersion, WriteMultipart, }; use bytes::Bytes; use futures::stream::FuturesUnordered; @@ -1196,3 +1196,33 @@ pub async fn multipart_race_condition(storage: &dyn ObjectStore, last_writer_win )); } } + +/// Tests performing out of order multipart uploads +pub async fn multipart_out_of_order(storage: &dyn ObjectStore) { + let path = Path::from("test_multipart_out_of_order"); + let mut multipart_upload = storage.put_multipart(&path).await.unwrap(); + + let part1 = std::iter::repeat(b'1') + .take(5 * 1024 * 1024) + .collect::(); + let part2 = std::iter::repeat(b'2') + .take(5 * 1024 * 1024) + .collect::(); + let part3 = std::iter::repeat(b'3') + .take(5 * 1024 * 1024) + .collect::(); + let full = [part1.as_ref(), part2.as_ref(), part3.as_ref()].concat(); + + let fut1 = multipart_upload.put_part(part1.into()); + let fut2 = multipart_upload.put_part(part2.into()); + let fut3 = multipart_upload.put_part(part3.into()); + fut2.await.unwrap(); + fut3.await.unwrap(); + fut1.await.unwrap(); + + multipart_upload.complete().await.unwrap(); + + let result = storage.get(&path).await.unwrap(); + let bytes = result.bytes().await.unwrap(); + assert_eq!(bytes, full); +} From a246ba5c07e8a3cf9b6c555dbd8c11e8b1bff842 Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Sun, 2 Feb 2025 07:12:49 -0500 Subject: [PATCH 2/2] Update object_store/src/integration.rs --- object_store/src/integration.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/object_store/src/integration.rs b/object_store/src/integration.rs index 1d082d1a7c9d..5a133f72d94a 100644 --- a/object_store/src/integration.rs +++ b/object_store/src/integration.rs @@ -1216,6 +1216,7 @@ pub async fn multipart_out_of_order(storage: &dyn ObjectStore) { let fut1 = multipart_upload.put_part(part1.into()); let fut2 = multipart_upload.put_part(part2.into()); let fut3 = multipart_upload.put_part(part3.into()); + // note order is 2,3,1 , different than the parts were created in fut2.await.unwrap(); fut3.await.unwrap(); fut1.await.unwrap();