deadpool_redis/cluster/config.rs
1pub use crate::config::ConfigError;
2use crate::ConnectionInfo;
3
4use super::{CreatePoolError, Pool, PoolBuilder, PoolConfig, Runtime};
5
6/// Configuration object.
7///
8/// # Example (from environment)
9///
10/// By enabling the `serde` feature you can read the configuration using the
11/// [`config`](https://crates.io/crates/config) crate as following:
12/// ```env
13/// REDIS_CLUSTER__URLS=redis://127.0.0.1:7000,redis://127.0.0.1:7001
14/// REDIS_CLUSTER__READ_FROM_REPLICAS=true
15/// REDIS_CLUSTER__POOL__MAX_SIZE=16
16/// REDIS_CLUSTER__POOL__TIMEOUTS__WAIT__SECS=2
17/// REDIS_CLUSTER__POOL__TIMEOUTS__WAIT__NANOS=0
18/// ```
19/// ```rust
20/// #[derive(serde::Deserialize)]
21/// struct Config {
22/// redis_cluster: deadpool_redis::cluster::Config,
23/// }
24///
25/// impl Config {
26/// pub fn from_env() -> Result<Self, config::ConfigError> {
27/// let mut cfg = config::Config::builder()
28/// .add_source(
29/// config::Environment::default()
30/// .separator("__")
31/// .try_parsing(true)
32/// .list_separator(","),
33/// )
34/// .build()?;
35/// cfg.try_deserialize()
36/// }
37/// }
38/// ```
39#[derive(Clone, Debug)]
40#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
41pub struct Config {
42 /// Redis URLs.
43 ///
44 /// See [Connection Parameters](redis#connection-parameters).
45 pub urls: Option<Vec<String>>,
46
47 /// [`redis::ConnectionInfo`] structures.
48 pub connections: Option<Vec<ConnectionInfo>>,
49
50 /// Pool configuration.
51 pub pool: Option<PoolConfig>,
52
53 /// Enables or disables reading from replica nodes in a Redis cluster.
54 ///
55 /// When set to `true`, read operations may be distributed across
56 /// replica nodes, which can help in load balancing read requests.
57 /// When set to `false`, all read operations will be directed to the
58 /// master node(s). This option is particularly useful in a high-availability
59 /// setup where read scalability is needed.
60 ///
61 /// Default is `false`.
62 #[cfg_attr(feature = "serde", serde(default))]
63 pub read_from_replicas: bool,
64}
65
66impl Config {
67 /// Creates a new [`Pool`] using this [`Config`].
68 ///
69 /// # Errors
70 ///
71 /// See [`CreatePoolError`] for details.
72 pub fn create_pool(&self, runtime: Option<Runtime>) -> Result<Pool, CreatePoolError> {
73 let mut builder = self.builder().map_err(CreatePoolError::Config)?;
74 if let Some(runtime) = runtime {
75 builder = builder.runtime(runtime);
76 }
77 builder.build().map_err(CreatePoolError::Build)
78 }
79
80 /// Creates a new [`PoolBuilder`] using this [`Config`].
81 ///
82 /// # Errors
83 ///
84 /// See [`ConfigError`] for details.
85 pub fn builder(&self) -> Result<PoolBuilder, ConfigError> {
86 let manager = match (&self.urls, &self.connections) {
87 (Some(urls), None) => super::Manager::new(
88 urls.iter().map(|url| url.as_str()).collect(),
89 self.read_from_replicas,
90 )?,
91 (None, Some(connections)) => {
92 super::Manager::new(connections.clone(), self.read_from_replicas)?
93 }
94 (None, None) => {
95 super::Manager::new(vec![ConnectionInfo::default()], self.read_from_replicas)?
96 }
97 (Some(_), Some(_)) => return Err(ConfigError::UrlAndConnectionSpecified),
98 };
99 let pool_config = self.get_pool_config();
100 Ok(Pool::builder(manager).config(pool_config))
101 }
102
103 /// Returns [`deadpool::managed::PoolConfig`] which can be used to construct
104 /// a [`deadpool::managed::Pool`] instance.
105 #[must_use]
106 pub fn get_pool_config(&self) -> PoolConfig {
107 self.pool.unwrap_or_default()
108 }
109
110 /// Creates a new [`Config`] from the given Redis URL (like
111 /// `redis://127.0.0.1`).
112 #[must_use]
113 pub fn from_urls<T: Into<Vec<String>>>(urls: T) -> Config {
114 Config {
115 urls: Some(urls.into()),
116 connections: None,
117 pool: None,
118 read_from_replicas: false,
119 }
120 }
121}
122
123impl Default for Config {
124 fn default() -> Self {
125 Self {
126 urls: None,
127 connections: Some(vec![ConnectionInfo::default()]),
128 pool: None,
129 read_from_replicas: false,
130 }
131 }
132}