This is an automated email from the ASF dual-hosted git repository.

xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal.git


The following commit(s) were added to refs/heads/main by this push:
     new 1439c764c fix(services/oss): fix batch delete with version for oss 
(#5687)
1439c764c is described below

commit 1439c764cdec52ee7a04a4cae0b949af2f45a3ce
Author: meteorgan <[email protected]>
AuthorDate: Mon Mar 3 21:30:50 2025 +0800

    fix(services/oss): fix batch delete with version for oss (#5687)
    
    fix oss
---
 core/src/services/oss/core.rs   | 14 ++++++++++++--
 core/src/services/oss/delete.rs | 28 ++++++++++++++--------------
 2 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/core/src/services/oss/core.rs b/core/src/services/oss/core.rs
index 2f9116b86..185047b25 100644
--- a/core/src/services/oss/core.rs
+++ b/core/src/services/oss/core.rs
@@ -571,7 +571,10 @@ impl OssCore {
         self.send(req).await
     }
 
-    pub async fn oss_delete_objects(&self, paths: Vec<String>) -> 
Result<Response<Buffer>> {
+    pub async fn oss_delete_objects(
+        &self,
+        paths: Vec<(String, OpDelete)>,
+    ) -> Result<Response<Buffer>> {
         let url = format!("{}/?delete", self.endpoint);
 
         let req = Request::post(&url);
@@ -579,8 +582,9 @@ impl OssCore {
         let content = quick_xml::se::to_string(&DeleteObjectsRequest {
             object: paths
                 .into_iter()
-                .map(|path| DeleteObjectsRequestObject {
+                .map(|(path, op)| DeleteObjectsRequestObject {
                     key: build_abs_path(&self.root, &path),
+                    version_id: op.version().map(|v| v.to_owned()),
                 })
                 .collect(),
         })
@@ -735,6 +739,8 @@ pub struct DeleteObjectsRequest {
 #[serde(rename_all = "PascalCase")]
 pub struct DeleteObjectsRequestObject {
     pub key: String,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub version_id: Option<String>,
 }
 
 /// Result of DeleteObjects.
@@ -748,6 +754,7 @@ pub struct DeleteObjectsResult {
 #[serde(rename_all = "PascalCase")]
 pub struct DeleteObjectsResultDeleted {
     pub key: String,
+    pub version_id: Option<String>,
 }
 
 #[derive(Default, Debug, Deserialize)]
@@ -866,12 +873,15 @@ mod tests {
             object: vec![
                 DeleteObjectsRequestObject {
                     key: "multipart.data".to_string(),
+                    version_id: None,
                 },
                 DeleteObjectsRequestObject {
                     key: "test.jpg".to_string(),
+                    version_id: None,
                 },
                 DeleteObjectsRequestObject {
                     key: "demo.jpg".to_string(),
+                    version_id: None,
                 },
             ],
         };
diff --git a/core/src/services/oss/delete.rs b/core/src/services/oss/delete.rs
index 544cf242c..f12e0eee1 100644
--- a/core/src/services/oss/delete.rs
+++ b/core/src/services/oss/delete.rs
@@ -50,17 +50,12 @@ impl oio::BatchDelete for OssDeleter {
     async fn delete_batch(&self, batch: Vec<(String, OpDelete)>) -> 
Result<BatchDeleteResult> {
         // Sadly, OSS will not return failed keys, so we will build
         // a set to calculate the failed keys.
-        let mut keys = HashSet::new();
-
-        let paths = batch
-            .into_iter()
-            .map(|(p, _)| {
-                keys.insert(p.clone());
-                p
-            })
+        let mut keys: HashSet<(String, OpDelete)> = batch
+            .iter()
+            .map(|path| (path.0.to_owned(), path.1.clone()))
             .collect();
 
-        let resp = self.core.oss_delete_objects(paths).await?;
+        let resp = self.core.oss_delete_objects(batch).await?;
 
         let status = resp.status();
 
@@ -87,14 +82,19 @@ impl oio::BatchDelete for OssDeleter {
 
         for i in result.deleted {
             let path = build_rel_path(&self.core.root, &i.key);
-            keys.remove(&path);
-            batched_result.succeeded.push((path, OpDelete::default()));
+            let mut op = OpDelete::default();
+            if let Some(version) = &i.version_id {
+                op = op.with_version(version);
+            }
+            let object = (path, op);
+            keys.remove(&object);
+            batched_result.succeeded.push(object);
         }
         // TODO: we should handle those errors with code.
-        for i in keys {
+        for (path, op) in keys {
             batched_result.failed.push((
-                i,
-                OpDelete::default(),
+                path,
+                op,
                 Error::new(
                     ErrorKind::Unexpected,
                     "oss delete this key failed for reason we don't know",

Reply via email to