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/incubator-opendal.git
The following commit(s) were added to refs/heads/main by this push:
new 91661d4aa feat(services): add RedisConfig (#3498)
91661d4aa is described below
commit 91661d4aaa490c93563feebdcc69efdb935d0ebe
Author: hoslo <[email protected]>
AuthorDate: Tue Nov 7 17:50:26 2023 +0800
feat(services): add RedisConfig (#3498)
---
core/src/services/mod.rs | 4 +-
core/src/services/redis/backend.rs | 100 ++++++++++++++++++++----------------
core/src/services/redis/mod.rs | 1 +
core/src/services/sqlite/backend.rs | 10 ++--
4 files changed, 66 insertions(+), 49 deletions(-)
diff --git a/core/src/services/mod.rs b/core/src/services/mod.rs
index 2816f6cff..042f5660c 100644
--- a/core/src/services/mod.rs
+++ b/core/src/services/mod.rs
@@ -144,7 +144,9 @@ pub use self::persy::Persy;
#[cfg(feature = "services-redis")]
mod redis;
#[cfg(feature = "services-redis")]
-pub use self::redis::Redis;
+pub use redis::Redis;
+#[cfg(feature = "services-redis")]
+pub use redis::RedisConfig;
#[cfg(feature = "services-rocksdb")]
mod rocksdb;
diff --git a/core/src/services/redis/backend.rs
b/core/src/services/redis/backend.rs
index a777b9345..c083d9677 100644
--- a/core/src/services/redis/backend.rs
+++ b/core/src/services/redis/backend.rs
@@ -33,6 +33,7 @@ use redis::ConnectionAddr;
use redis::ConnectionInfo;
use redis::RedisConnectionInfo;
use redis::RedisError;
+use serde::Deserialize;
use tokio::sync::OnceCell;
use crate::raw::adapters::kv;
@@ -42,10 +43,11 @@ use crate::*;
const DEFAULT_REDIS_ENDPOINT: &str = "tcp://127.0.0.1:6379";
const DEFAULT_REDIS_PORT: u16 = 6379;
-/// [Redis](https://redis.io/) services support.
-#[doc = include_str!("docs.md")]
-#[derive(Clone, Default)]
-pub struct RedisBuilder {
+/// Config for Redis services support.
+#[derive(Default, Deserialize, Clone)]
+#[serde(default)]
+#[non_exhaustive]
+pub struct RedisConfig {
/// network address of the Redis service. Can be "tcp://127.0.0.1:6379",
e.g.
///
/// default is "tcp://127.0.0.1:6379"
@@ -74,24 +76,42 @@ pub struct RedisBuilder {
default_ttl: Option<Duration>,
}
-impl Debug for RedisBuilder {
+impl Debug for RedisConfig {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- let mut ds = f.debug_struct("Builder");
- ds.field("db", &self.db.to_string());
- ds.field("root", &self.root);
+ let mut d = f.debug_struct("RedisConfig");
+
+ d.field("db", &self.db.to_string());
+ d.field("root", &self.root);
if let Some(endpoint) = self.endpoint.clone() {
- ds.field("endpoint", &endpoint);
+ d.field("endpoint", &endpoint);
}
if let Some(cluster_endpoints) = self.cluster_endpoints.clone() {
- ds.field("cluster_endpoints", &cluster_endpoints);
+ d.field("cluster_endpoints", &cluster_endpoints);
}
if let Some(username) = self.username.clone() {
- ds.field("username", &username);
+ d.field("username", &username);
}
if self.password.is_some() {
- ds.field("password", &"<redacted>");
+ d.field("password", &"<redacted>");
}
- ds.finish()
+
+ d.finish_non_exhaustive()
+ }
+}
+
+/// [Redis](https://redis.io/) services support.
+#[doc = include_str!("docs.md")]
+#[derive(Clone, Default)]
+pub struct RedisBuilder {
+ config: RedisConfig,
+}
+
+impl Debug for RedisBuilder {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ let mut d = f.debug_struct("RedisBuilder");
+
+ d.field("config", &self.config);
+ d.finish_non_exhaustive()
}
}
@@ -104,7 +124,7 @@ impl RedisBuilder {
/// - "unix" or "redis+unix": unix socket connection
pub fn endpoint(&mut self, endpoint: &str) -> &mut Self {
if !endpoint.is_empty() {
- self.endpoint = Some(endpoint.to_owned());
+ self.config.endpoint = Some(endpoint.to_owned());
}
self
}
@@ -118,7 +138,7 @@ impl RedisBuilder {
/// - "unix" or "redis+unix": unix socket connection
pub fn cluster_endpoints(&mut self, cluster_endpoints: &str) -> &mut Self {
if !cluster_endpoints.is_empty() {
- self.cluster_endpoints = Some(cluster_endpoints.to_owned());
+ self.config.cluster_endpoints = Some(cluster_endpoints.to_owned());
}
self
}
@@ -128,7 +148,7 @@ impl RedisBuilder {
/// default: no username
pub fn username(&mut self, username: &str) -> &mut Self {
if !username.is_empty() {
- self.username = Some(username.to_owned());
+ self.config.username = Some(username.to_owned());
}
self
}
@@ -138,7 +158,7 @@ impl RedisBuilder {
/// default: no password
pub fn password(&mut self, password: &str) -> &mut Self {
if !password.is_empty() {
- self.password = Some(password.to_owned());
+ self.config.password = Some(password.to_owned());
}
self
}
@@ -147,7 +167,7 @@ impl RedisBuilder {
///
/// default: 0
pub fn db(&mut self, db: i64) -> &mut Self {
- self.db = db;
+ self.config.db = db;
self
}
@@ -155,7 +175,7 @@ impl RedisBuilder {
///
/// If set, we will specify `EX` for write operations.
pub fn default_ttl(&mut self, ttl: Duration) -> &mut Self {
- self.default_ttl = Some(ttl);
+ self.config.default_ttl = Some(ttl);
self
}
@@ -164,7 +184,7 @@ impl RedisBuilder {
/// 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
}
@@ -175,38 +195,31 @@ impl Builder for RedisBuilder {
type Accessor = RedisBackend;
fn from_map(map: HashMap<String, String>) -> Self {
- let mut builder = RedisBuilder::default();
-
- map.get("root").map(|v| builder.root(v));
- map.get("endpoint").map(|v| builder.endpoint(v));
- map.get("cluster_endpoints")
- .map(|v| builder.cluster_endpoints(v));
- map.get("username").map(|v| builder.username(v));
- map.get("password").map(|v| builder.password(v));
- map.get("db")
- .map(|v| v.parse::<i64>().map(|v| builder.db(v)));
-
- builder
+ let config = RedisConfig::deserialize(ConfigDeserializer::new(map))
+ .expect("config deserialize must succeed");
+
+ RedisBuilder { config }
}
fn build(&mut self) -> Result<Self::Accessor> {
let root = normalize_root(
- self.root
+ self.config
+ .root
.clone()
.unwrap_or_else(|| "/".to_string())
.as_str(),
);
- if let Some(endpoints) = self.cluster_endpoints.clone() {
+ if let Some(endpoints) = self.config.cluster_endpoints.clone() {
let mut cluster_endpoints: Vec<ConnectionInfo> = Vec::default();
for endpoint in endpoints.split(',') {
cluster_endpoints.push(self.get_connection_info(endpoint.to_string())?);
}
let mut client_builder =
ClusterClientBuilder::new(cluster_endpoints);
- if let Some(username) = &self.username {
+ if let Some(username) = &self.config.username {
client_builder = client_builder.username(username.clone());
}
- if let Some(password) = &self.password {
+ if let Some(password) = &self.config.password {
client_builder = client_builder.password(password.clone());
}
let client = client_builder.build()?;
@@ -218,11 +231,12 @@ impl Builder for RedisBuilder {
client: None,
cluster_client: Some(client),
conn,
- default_ttl: self.default_ttl,
+ default_ttl: self.config.default_ttl,
})
.with_root(&root))
} else {
let endpoint = self
+ .config
.endpoint
.clone()
.unwrap_or_else(|| DEFAULT_REDIS_ENDPOINT.to_string());
@@ -231,8 +245,8 @@ impl Builder for RedisBuilder {
Client::open(self.get_connection_info(endpoint.clone())?).map_err(|e| {
Error::new(ErrorKind::ConfigInvalid, "invalid or
unsupported scheme")
.with_context("service", Scheme::Redis)
- .with_context("endpoint",
self.endpoint.as_ref().unwrap())
- .with_context("db", self.db.to_string())
+ .with_context("endpoint",
self.config.endpoint.as_ref().unwrap())
+ .with_context("db", self.config.db.to_string())
.set_source(e)
})?;
@@ -242,7 +256,7 @@ impl Builder for RedisBuilder {
client: Some(client),
cluster_client: None,
conn,
- default_ttl: self.default_ttl,
+ default_ttl: self.config.default_ttl,
})
.with_root(&root))
}
@@ -293,9 +307,9 @@ impl RedisBuilder {
};
let redis_info = RedisConnectionInfo {
- db: self.db,
- username: self.username.clone(),
- password: self.password.clone(),
+ db: self.config.db,
+ username: self.config.username.clone(),
+ password: self.config.password.clone(),
};
Ok(ConnectionInfo {
diff --git a/core/src/services/redis/mod.rs b/core/src/services/redis/mod.rs
index e778e35b5..68668eecf 100644
--- a/core/src/services/redis/mod.rs
+++ b/core/src/services/redis/mod.rs
@@ -17,3 +17,4 @@
mod backend;
pub use backend::RedisBuilder as Redis;
+pub use backend::RedisConfig;
diff --git a/core/src/services/sqlite/backend.rs
b/core/src/services/sqlite/backend.rs
index 79a513d4a..5595979b9 100644
--- a/core/src/services/sqlite/backend.rs
+++ b/core/src/services/sqlite/backend.rs
@@ -44,22 +44,22 @@ pub struct SqliteConfig {
/// - `file://data.db`
///
/// For more information, please refer to [Opening A New Database
Connection](http://www.sqlite.org/c3ref/open.html)
- connection_string: Option<String>,
+ pub connection_string: Option<String>,
/// Set the table name of the sqlite service to read/write.
- table: Option<String>,
+ pub table: Option<String>,
/// Set the key field name of the sqlite service to read/write.
///
/// Default to `key` if not specified.
- key_field: Option<String>,
+ pub key_field: Option<String>,
/// Set the value field name of the sqlite service to read/write.
///
/// Default to `value` if not specified.
- value_field: Option<String>,
+ pub value_field: Option<String>,
/// set the working directory, all operations will be performed under it.
///
/// default: "/"
- root: Option<String>,
+ pub root: Option<String>,
}
impl Debug for SqliteConfig {