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}