opendal/services/s3/
delete.rs1use super::core::*;
19use super::error::{parse_error, parse_s3_error_code};
20use crate::raw::oio::BatchDeleteResult;
21use crate::raw::*;
22use crate::*;
23use bytes::Buf;
24use http::StatusCode;
25use std::sync::Arc;
26
27pub struct S3Deleter {
28 core: Arc<S3Core>,
29}
30
31impl S3Deleter {
32 pub fn new(core: Arc<S3Core>) -> Self {
33 Self { core }
34 }
35}
36
37impl oio::BatchDelete for S3Deleter {
38 async fn delete_once(&self, path: String, args: OpDelete) -> Result<()> {
39 if self.core.root == "/" && path == "/" {
41 return Ok(());
42 }
43
44 let resp = self.core.s3_delete_object(&path, &args).await?;
45
46 let status = resp.status();
47
48 match status {
49 StatusCode::NO_CONTENT => Ok(()),
50 StatusCode::NOT_FOUND => Ok(()),
54 _ => Err(parse_error(resp)),
55 }
56 }
57
58 async fn delete_batch(&self, batch: Vec<(String, OpDelete)>) -> Result<BatchDeleteResult> {
59 let resp = self.core.s3_delete_objects(batch).await?;
60
61 let status = resp.status();
62 if status != StatusCode::OK {
63 return Err(parse_error(resp));
64 }
65
66 let bs = resp.into_body();
67
68 let mut result: DeleteObjectsResult =
69 quick_xml::de::from_reader(bs.reader()).map_err(new_xml_deserialize_error)?;
70
71 if result.deleted.is_empty() {
73 let err = result.error.remove(0);
74 return Err(parse_delete_objects_result_error(err));
75 }
76
77 let mut batched_result = BatchDeleteResult {
78 succeeded: Vec::with_capacity(result.deleted.len()),
79 failed: Vec::with_capacity(result.error.len()),
80 };
81 for i in result.deleted {
82 let path = build_rel_path(&self.core.root, &i.key);
83 let mut op = OpDelete::new();
84 if let Some(version_id) = i.version_id {
85 op = op.with_version(version_id.as_str());
86 }
87 batched_result.succeeded.push((path, op));
88 }
89 for i in result.error {
90 let path = build_rel_path(&self.core.root, &i.key);
91 let mut op = OpDelete::new();
92 if let Some(version_id) = &i.version_id {
93 op = op.with_version(version_id.as_str());
94 }
95 batched_result
96 .failed
97 .push((path, op, parse_delete_objects_result_error(i)));
98 }
99
100 Ok(batched_result)
101 }
102}
103
104fn parse_delete_objects_result_error(err: DeleteObjectsResultError) -> Error {
105 let (kind, retryable) =
106 parse_s3_error_code(err.code.as_str()).unwrap_or((ErrorKind::Unexpected, false));
107 let mut err: Error = Error::new(kind, format!("{err:?}"));
108 if retryable {
109 err = err.set_temporary();
110 }
111 err
112}