Skip to main content

deadpool_memcached/
config.rs

1use std::convert::Infallible;
2
3use crate::{CreatePoolError, Manager, Pool, PoolBuilder, PoolConfig, Runtime};
4
5/// Configuration object.
6///
7/// # Example (from environment)
8///
9/// You can read the configuration using the
10/// [`config`](https://crates.io/crates/config) crate as following:
11/// ```env
12/// MEMCACHED__ADDR=127.0.0.1:11211
13/// MEMCACHED__POOL__MAX_SIZE=16
14/// MEMCACHED__POOL__TIMEOUTS__WAIT__SECS=5
15/// MEMCACHED__POOL__TIMEOUTS__WAIT__NANOS=0
16/// ```
17/// ```rust,ignore
18/// #[derive(serde::Deserialize, serde::Serialize)]
19/// struct Config {
20///     memcached: deadpool_memcached::Config,
21/// }
22/// impl Config {
23///     pub fn from_env() -> Result<Self, config::ConfigError> {
24///         let mut cfg = config::Config::builder()
25///            .add_source(config::Environment::default().separator("__"))
26///            .build()?;
27///            cfg.try_deserialize()
28///     }
29/// }
30/// ```
31#[derive(Clone, Debug, Default)]
32pub struct Config {
33    /// Memcached address.
34    pub addr: Option<String>,
35
36    /// [`Pool`] configuration.
37    pub pool: Option<PoolConfig>,
38}
39
40impl Config {
41    /// Creates a new [`Config`] with the given Memcached address.
42    #[must_use]
43    pub fn new(addr: impl Into<String>) -> Self {
44        Self {
45            addr: Some(addr.into()),
46            pool: None,
47        }
48    }
49
50    /// Creates a new [`Pool`] using this [`Config`].
51    ///
52    /// A [`Runtime`] is required if any [`Timeouts`] are configured on the
53    /// [`PoolConfig`] (`wait`, `create` or `recycle`). Pass `None` if you do
54    /// not need timeouts.
55    ///
56    /// [`Timeouts`]: deadpool::managed::Timeouts
57    ///
58    /// # Errors
59    ///
60    /// See [`CreatePoolError`] for details.
61    pub fn create_pool(&self, runtime: Option<Runtime>) -> Result<Pool, CreatePoolError> {
62        let mut builder = self.builder().map_err(CreatePoolError::Config)?;
63        if let Some(runtime) = runtime {
64            builder = builder.runtime(runtime);
65        }
66        builder.build().map_err(CreatePoolError::Build)
67    }
68
69    /// Creates a new [`PoolBuilder`] using this [`Config`].
70    ///
71    /// # Errors
72    ///
73    /// See [`ConfigError`] for details.
74    pub fn builder(&self) -> Result<PoolBuilder, ConfigError> {
75        let manager = Manager::new(self.get_addr());
76        Ok(Pool::builder(manager).config(self.get_pool_config()))
77    }
78
79    /// Returns address used to connect to the Memcached server.
80    pub fn get_addr(&self) -> &str {
81        self.addr.as_deref().unwrap_or("127.0.0.1:11211")
82    }
83
84    /// Returns [`deadpool::managed::PoolConfig`] which can be used to construct
85    /// a [`deadpool::managed::Pool`] instance.
86    #[must_use]
87    pub fn get_pool_config(&self) -> PoolConfig {
88        self.pool.unwrap_or_default()
89    }
90}
91
92/// This error is returned if there is something wrong with the Memcached configuration.
93///
94/// This is just a type alias to [`Infallible`] at the moment as there
95/// is no validation happening at the configuration phase.
96pub type ConfigError = Infallible;
97
98#[cfg(test)]
99mod tests {
100    use super::Config;
101
102    #[test]
103    fn default_addr_is_localhost() {
104        let cfg = Config::default();
105        assert_eq!(cfg.get_addr(), "127.0.0.1:11211");
106    }
107
108    #[test]
109    fn new_sets_addr() {
110        let cfg = Config::new("cache.internal:11211");
111        assert_eq!(cfg.get_addr(), "cache.internal:11211");
112    }
113}