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 b8e778c48 feat(core): Implement write returns metadata for b2 (#5750)
b8e778c48 is described below
commit b8e778c488c835e3c45156f77e6c2ec0c6837beb
Author: hoslo <[email protected]>
AuthorDate: Thu Mar 13 20:47:38 2025 +0800
feat(core): Implement write returns metadata for b2 (#5750)
---
core/src/services/b2/backend.rs | 3 +++
core/src/services/b2/core.rs | 9 ++++++++
core/src/services/b2/writer.rs | 39 +++++++++++++++++++++++++++++++++--
core/src/types/capability.rs | 2 ++
core/tests/behavior/async_write.rs | 9 ++++++++
core/tests/behavior/blocking_write.rs | 6 ++++++
6 files changed, 66 insertions(+), 2 deletions(-)
diff --git a/core/src/services/b2/backend.rs b/core/src/services/b2/backend.rs
index 1796e60c4..9a7e86c08 100644
--- a/core/src/services/b2/backend.rs
+++ b/core/src/services/b2/backend.rs
@@ -212,6 +212,9 @@ impl Builder for B2Builder {
write_can_empty: true,
write_can_multi: true,
write_with_content_type: true,
+ write_has_content_md5: true,
+ write_has_content_length: true,
+ write_has_content_type: true,
// The min multipart size of b2 is 5 MiB.
//
// ref:
<https://www.backblaze.com/docs/cloud-storage-large-files>
diff --git a/core/src/services/b2/core.rs b/core/src/services/b2/core.rs
index 4ee2f1d84..2c2733b0e 100644
--- a/core/src/services/b2/core.rs
+++ b/core/src/services/b2/core.rs
@@ -622,6 +622,15 @@ pub struct ListFileNamesResponse {
pub next_file_name: Option<String>,
}
+/// Response of
[b2-finish-large-file](https://www.backblaze.com/apidocs/b2-finish-large-file).
+#[derive(Debug, Clone, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct UploadResponse {
+ pub content_length: u64,
+ pub content_md5: Option<String>,
+ pub content_type: Option<String>,
+}
+
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct File {
diff --git a/core/src/services/b2/writer.rs b/core/src/services/b2/writer.rs
index 5512c24ad..8213642e3 100644
--- a/core/src/services/b2/writer.rs
+++ b/core/src/services/b2/writer.rs
@@ -23,6 +23,7 @@ use http::StatusCode;
use super::core::B2Core;
use super::core::StartLargeFileResponse;
use super::core::UploadPartResponse;
+use super::core::UploadResponse;
use super::error::parse_error;
use crate::raw::*;
use crate::*;
@@ -44,6 +45,22 @@ impl B2Writer {
op,
}
}
+
+ pub fn parse_body_into_meta(path: &str, resp: UploadResponse) -> Metadata {
+ let mut meta = Metadata::new(EntryMode::from_path(path));
+
+ if let Some(md5) = resp.content_md5 {
+ meta.set_content_md5(&md5);
+ }
+
+ if let Some(content_type) = resp.content_type {
+ meta.set_content_type(&content_type);
+ }
+
+ meta.set_content_length(resp.content_length);
+
+ meta
+ }
}
impl oio::MultipartWrite for B2Writer {
@@ -56,7 +73,16 @@ impl oio::MultipartWrite for B2Writer {
let status = resp.status();
match status {
- StatusCode::OK => Ok(Metadata::default()),
+ StatusCode::OK => {
+ let bs = resp.into_body();
+
+ let result: UploadResponse =
+
serde_json::from_reader(bs.reader()).map_err(new_json_deserialize_error)?;
+
+ let meta = Self::parse_body_into_meta(&self.path, result);
+
+ Ok(meta)
+ }
_ => Err(parse_error(resp)),
}
}
@@ -138,7 +164,16 @@ impl oio::MultipartWrite for B2Writer {
let status = resp.status();
match status {
- StatusCode::OK => Ok(Metadata::default()),
+ StatusCode::OK => {
+ let bs = resp.into_body();
+
+ let result: UploadResponse =
+
serde_json::from_reader(bs.reader()).map_err(new_json_deserialize_error)?;
+
+ let meta = Self::parse_body_into_meta(&self.path, result);
+
+ Ok(meta)
+ }
_ => Err(parse_error(resp)),
}
}
diff --git a/core/src/types/capability.rs b/core/src/types/capability.rs
index 10ef127b9..e14f8b8f2 100644
--- a/core/src/types/capability.rs
+++ b/core/src/types/capability.rs
@@ -168,6 +168,8 @@ pub struct Capability {
pub write_has_version: bool,
/// Indicates whether content MD5 checksum is available in write response
pub write_has_content_md5: bool,
+ /// Indicates whether content type information is available in write
response
+ pub write_has_content_type: bool,
/// Indicates if directory creation is supported.
pub create_dir: bool,
diff --git a/core/tests/behavior/async_write.rs
b/core/tests/behavior/async_write.rs
index 867dc8833..73ff292e8 100644
--- a/core/tests/behavior/async_write.rs
+++ b/core/tests/behavior/async_write.rs
@@ -276,6 +276,9 @@ pub async fn test_write_returns_metadata(op: Operator) ->
Result<()> {
if cap.write_has_content_md5 {
assert_eq!(stat_meta.content_md5(), meta.content_md5());
}
+ if cap.write_has_content_type {
+ assert_eq!(stat_meta.content_type(), meta.content_type());
+ }
Ok(())
}
@@ -605,6 +608,9 @@ pub async fn test_writer_return_metadata(op: Operator) ->
Result<()> {
if cap.write_has_content_md5 {
assert_eq!(stat_meta.content_md5(), meta.content_md5());
}
+ if cap.write_has_content_type {
+ assert_eq!(stat_meta.content_type(), meta.content_type());
+ }
Ok(())
}
@@ -674,6 +680,9 @@ pub async fn test_write_with_append_returns_metadata(op:
Operator) -> Result<()>
if cap.write_has_content_md5 {
assert_eq!(stat_meta.content_md5(), meta.content_md5());
}
+ if cap.write_has_content_type {
+ assert_eq!(stat_meta.content_type(), meta.content_type());
+ }
Ok(())
}
diff --git a/core/tests/behavior/blocking_write.rs
b/core/tests/behavior/blocking_write.rs
index 6d1bd9372..c1dbd9c05 100644
--- a/core/tests/behavior/blocking_write.rs
+++ b/core/tests/behavior/blocking_write.rs
@@ -112,6 +112,9 @@ pub fn test_blocking_write_returns_metadata(op:
BlockingOperator) -> Result<()>
if cap.write_has_content_md5 {
assert_eq!(meta.content_md5(), stat_meta.content_md5());
}
+ if cap.write_has_content_type {
+ assert_eq!(meta.content_type(), stat_meta.content_type());
+ }
Ok(())
}
@@ -172,6 +175,9 @@ pub fn test_blocking_write_with_append_returns_metadata(op:
BlockingOperator) ->
if cap.write_has_content_md5 {
assert_eq!(meta.content_md5(), stat_meta.content_md5());
}
+ if cap.write_has_content_type {
+ assert_eq!(meta.content_type(), stat_meta.content_type());
+ }
Ok(())
}