use crate::cache_redis::{RedisCacheConfig, RedisCacheError, RedisCacheResult};
#[derive(Debug, Clone)]
pub struct RedisClientFactory {
config: RedisCacheConfig,
}
impl RedisClientFactory {
pub fn new(config: RedisCacheConfig) -> RedisCacheResult<Self> {
config.validate()?;
Ok(Self { config })
}
pub fn url(&self) -> &str {
&self.config.url
}
pub fn create_client(&self) -> RedisCacheResult<redis::Client> {
redis::Client::open(self.config.url.as_str())
.map_err(|error| RedisCacheError::Connection(error.to_string()))
}
pub fn create_cluster_client(&self) -> RedisCacheResult<redis::cluster::ClusterClient> {
let nodes = cluster_startup_nodes(&self.config.url)?;
let mut builder = redis::cluster::ClusterClient::builder(nodes)
.retries(self.config.cluster.max_redirects.max(1))
.connection_timeout(self.config.connect_timeout)
.response_timeout(self.config.command_timeout);
if self.config.cluster.read_from_replicas {
builder = builder.read_from_replicas();
}
builder
.build()
.map_err(|error| RedisCacheError::Connection(error.to_string()))
}
}
pub fn cluster_startup_nodes(urls: &str) -> RedisCacheResult<Vec<String>> {
let nodes = urls
.split(',')
.map(str::trim)
.filter(|url| !url.is_empty())
.map(str::to_string)
.collect::<Vec<_>>();
if nodes.is_empty() {
return Err(RedisCacheError::InvalidUrl {
url: urls.to_string(),
});
}
Ok(nodes)
}
#[cfg(test)]
mod tests {
use super::cluster_startup_nodes;
#[test]
fn cluster_startup_nodes_trim_empty_entries() {
let nodes = cluster_startup_nodes(" redis://127.0.0.1:7000, ,redis://127.0.0.1:7001 ")
.expect("nodes");
assert_eq!(
nodes,
vec!["redis://127.0.0.1:7000", "redis://127.0.0.1:7001"]
);
}
}