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 775b27c078 refactor(service/d1): Add D1Config (#4129)
775b27c078 is described below
commit 775b27c0782f392b7d2686fafd13aec45acc071e
Author: 纪华裕 <[email protected]>
AuthorDate: Fri Feb 2 14:49:04 2024 +0800
refactor(service/d1): Add D1Config (#4129)
* Add D1Config #3240
* Add D1Config #3240
* format code
* fix bug
* fix cargo clippy
---
core/src/services/d1/backend.rs | 100 +++++++++++++++++++++++++---------------
core/src/services/d1/mod.rs | 2 +
core/src/services/mod.rs | 2 +
3 files changed, 66 insertions(+), 38 deletions(-)
diff --git a/core/src/services/d1/backend.rs b/core/src/services/d1/backend.rs
index 5555c6bd57..203ad4d2d9 100644
--- a/core/src/services/d1/backend.rs
+++ b/core/src/services/d1/backend.rs
@@ -23,6 +23,7 @@ use async_trait::async_trait;
use http::header;
use http::Request;
use http::StatusCode;
+use serde::Deserialize;
use serde_json::Value;
use super::error::parse_error;
@@ -32,29 +33,52 @@ use crate::raw::*;
use crate::ErrorKind;
use crate::*;
+/// Config for [Cloudflare D1](https://developers.cloudflare.com/d1) backend
support.
+#[derive(Default, Deserialize)]
+#[serde(default)]
+#[non_exhaustive]
+pub struct D1Config {
+ /// Set the token of cloudflare api.
+ pub token: Option<String>,
+ /// Set the account id of cloudflare api.
+ pub account_id: Option<String>,
+ /// Set the database id of cloudflare api.
+ pub database_id: Option<String>,
+
+ /// Set the working directory of OpenDAL.
+ pub root: Option<String>,
+ /// Set the table of D1 Database.
+ pub table: Option<String>,
+ /// Set the key field of D1 Database.
+ pub key_field: Option<String>,
+ /// Set the value field of D1 Database.
+ pub value_field: Option<String>,
+}
+
+impl Debug for D1Config {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ let mut ds = f.debug_struct("D1Config");
+ ds.field("root", &self.root);
+ ds.field("table", &self.table);
+ ds.field("key_field", &self.key_field);
+ ds.field("value_field", &self.value_field);
+ ds.finish_non_exhaustive()
+ }
+}
+
#[doc = include_str!("docs.md")]
#[derive(Default)]
pub struct D1Builder {
- token: Option<String>,
- account_id: Option<String>,
- database_id: Option<String>,
+ config: D1Config,
http_client: Option<HttpClient>,
- root: Option<String>,
-
- table: Option<String>,
- key_field: Option<String>,
- value_field: Option<String>,
}
impl Debug for D1Builder {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- let mut ds = f.debug_struct("D1Builder");
- ds.field("root", &self.root);
- ds.field("table", &self.table);
- ds.field("key_field", &self.key_field);
- ds.field("value_field", &self.value_field);
- ds.finish()
+ f.debug_struct("D1Builder")
+ .field("config", &self.config)
+ .finish()
}
}
@@ -64,7 +88,7 @@ impl D1Builder {
/// create a api token from
[here](https://dash.cloudflare.com/profile/api-tokens)
pub fn token(&mut self, token: &str) -> &mut Self {
if !token.is_empty() {
- self.token = Some(token.to_string());
+ self.config.token = Some(token.to_string());
}
self
}
@@ -75,7 +99,7 @@ impl D1Builder {
/// If not specified, it will return an error when building.
pub fn account_id(&mut self, account_id: &str) -> &mut Self {
if !account_id.is_empty() {
- self.account_id = Some(account_id.to_string());
+ self.config.account_id = Some(account_id.to_string());
}
self
}
@@ -86,7 +110,7 @@ impl D1Builder {
/// If not specified, it will return an error when building.
pub fn database_id(&mut self, database_id: &str) -> &mut Self {
if !database_id.is_empty() {
- self.database_id = Some(database_id.to_string());
+ self.config.database_id = Some(database_id.to_string());
}
self
}
@@ -96,7 +120,7 @@ impl D1Builder {
/// default: "/"
pub fn root(&mut self, root: &str) -> &mut Self {
if !root.is_empty() {
- self.root = Some(root.to_owned());
+ self.config.root = Some(root.to_owned());
}
self
}
@@ -106,7 +130,7 @@ impl D1Builder {
/// If not specified, it will return an error when building.
pub fn table(&mut self, table: &str) -> &mut Self {
if !table.is_empty() {
- self.table = Some(table.to_owned());
+ self.config.table = Some(table.to_owned());
}
self
}
@@ -116,7 +140,7 @@ impl D1Builder {
/// Default to `key` if not specified.
pub fn key_field(&mut self, key_field: &str) -> &mut Self {
if !key_field.is_empty() {
- self.key_field = Some(key_field.to_string());
+ self.config.key_field = Some(key_field.to_string());
}
self
}
@@ -126,7 +150,7 @@ impl D1Builder {
/// Default to `value` if not specified.
pub fn value_field(&mut self, value_field: &str) -> &mut Self {
if !value_field.is_empty() {
- self.value_field = Some(value_field.to_string());
+ self.config.value_field = Some(value_field.to_string());
}
self
}
@@ -137,32 +161,28 @@ impl Builder for D1Builder {
type Accessor = D1Backend;
fn from_map(map: HashMap<String, String>) -> Self {
- let mut builder = D1Builder::default();
- map.get("token").map(|v| builder.token(v));
- map.get("account_id").map(|v| builder.account_id(v));
- map.get("database_id").map(|v| builder.database_id(v));
-
- map.get("root").map(|v| builder.root(v));
- map.get("table").map(|v| builder.table(v));
- map.get("key_field").map(|v| builder.key_field(v));
- map.get("value_field").map(|v| builder.value_field(v));
- builder
+ Self {
+ config: D1Config::deserialize(ConfigDeserializer::new(map))
+ .expect("config deserialize must succeed"),
+ ..Default::default()
+ }
}
fn build(&mut self) -> Result<Self::Accessor> {
let mut authorization = None;
- if let Some(token) = &self.token {
+ let config = &self.config;
+ if let Some(token) = &config.token {
authorization = Some(format_authorization_by_bearer(token)?)
}
- let Some(account_id) = self.account_id.clone() else {
+ let Some(account_id) = config.account_id.clone() else {
return Err(Error::new(
ErrorKind::ConfigInvalid,
"account_id is required",
));
};
- let Some(database_id) = self.database_id.clone() else {
+ let Some(database_id) = config.database_id.clone() else {
return Err(Error::new(
ErrorKind::ConfigInvalid,
"database_id is required",
@@ -178,19 +198,23 @@ impl Builder for D1Builder {
})?
};
- let Some(table) = self.table.clone() else {
+ let Some(table) = config.table.clone() else {
return Err(Error::new(ErrorKind::ConfigInvalid, "table is
required"));
};
- let key_field = self.key_field.clone().unwrap_or_else(||
"key".to_string());
+ let key_field = config
+ .key_field
+ .clone()
+ .unwrap_or_else(|| "key".to_string());
- let value_field = self
+ let value_field = config
.value_field
.clone()
.unwrap_or_else(|| "value".to_string());
let root = normalize_root(
- self.root
+ config
+ .root
.clone()
.unwrap_or_else(|| "/".to_string())
.as_str(),
diff --git a/core/src/services/d1/mod.rs b/core/src/services/d1/mod.rs
index 9163a135c6..1fe63408af 100644
--- a/core/src/services/d1/mod.rs
+++ b/core/src/services/d1/mod.rs
@@ -18,4 +18,6 @@
mod backend;
mod error;
mod model;
+
pub use backend::D1Builder as D1;
+pub use backend::D1Config;
diff --git a/core/src/services/mod.rs b/core/src/services/mod.rs
index 16f467329b..de5c0cef02 100644
--- a/core/src/services/mod.rs
+++ b/core/src/services/mod.rs
@@ -291,6 +291,8 @@ pub use sqlite::SqliteConfig;
#[cfg(feature = "services-d1")]
mod d1;
#[cfg(feature = "services-d1")]
+pub use self::d1::D1Config;
+#[cfg(feature = "services-d1")]
pub use self::d1::D1;
#[cfg(feature = "services-azfile")]