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}