connpool/factories/
sync_factory.rs1use std::error::Error;
4
5use crate::core::errors::FactoryError;
6
7pub trait ConnectionFactory<T>: Send + Sync {
13 fn create(&self) -> Result<T, FactoryError>;
15
16 fn validate(&self, _conn: &T) -> bool {
18 true
19 }
20
21 fn reset(&self, _conn: &T) -> Result<(), FactoryError> {
23 Ok(())
24 }
25
26 fn close(&self, _conn: &T) -> Result<(), FactoryError> {
29 Ok(())
30 }
31
32 fn is_fatal_error(&self, _err: &(dyn Error + 'static)) -> bool {
35 false
36 }
37}
38
39impl<T> ConnectionFactory<T> for Box<dyn ConnectionFactory<T>> {
42 fn create(&self) -> Result<T, FactoryError> {
43 (**self).create()
44 }
45 fn validate(&self, conn: &T) -> bool {
46 (**self).validate(conn)
47 }
48 fn reset(&self, conn: &T) -> Result<(), FactoryError> {
49 (**self).reset(conn)
50 }
51 fn close(&self, conn: &T) -> Result<(), FactoryError> {
52 (**self).close(conn)
53 }
54 fn is_fatal_error(&self, err: &(dyn Error + 'static)) -> bool {
55 (**self).is_fatal_error(err)
56 }
57}
58
59type CreateFn<T> = Box<dyn Fn() -> Result<T, FactoryError> + Send + Sync>;
60type ValidateFn<T> = Box<dyn Fn(&T) -> bool + Send + Sync>;
61type ResetFn<T> = Box<dyn Fn(&T) -> Result<(), FactoryError> + Send + Sync>;
62type CloseFn<T> = Box<dyn Fn(&T) -> Result<(), FactoryError> + Send + Sync>;
63type IsFatalFn = Box<dyn Fn(&(dyn Error + 'static)) -> bool + Send + Sync>;
64
65pub struct FnFactory<T> {
68 create_fn: CreateFn<T>,
69 validate_fn: Option<ValidateFn<T>>,
70 reset_fn: Option<ResetFn<T>>,
71 close_fn: Option<CloseFn<T>>,
72 is_fatal_fn: Option<IsFatalFn>,
73}
74
75impl<T> FnFactory<T> {
76 pub fn new<F>(create: F) -> Self
78 where
79 F: Fn() -> Result<T, FactoryError> + Send + Sync + 'static,
80 {
81 Self {
82 create_fn: Box::new(create),
83 validate_fn: None,
84 reset_fn: None,
85 close_fn: None,
86 is_fatal_fn: None,
87 }
88 }
89
90 pub fn with_validate<F>(mut self, f: F) -> Self
92 where
93 F: Fn(&T) -> bool + Send + Sync + 'static,
94 {
95 self.validate_fn = Some(Box::new(f));
96 self
97 }
98
99 pub fn with_reset<F>(mut self, f: F) -> Self
101 where
102 F: Fn(&T) -> Result<(), FactoryError> + Send + Sync + 'static,
103 {
104 self.reset_fn = Some(Box::new(f));
105 self
106 }
107
108 pub fn with_close<F>(mut self, f: F) -> Self
110 where
111 F: Fn(&T) -> Result<(), FactoryError> + Send + Sync + 'static,
112 {
113 self.close_fn = Some(Box::new(f));
114 self
115 }
116
117 pub fn with_is_fatal_error<F>(mut self, f: F) -> Self
119 where
120 F: Fn(&(dyn Error + 'static)) -> bool + Send + Sync + 'static,
121 {
122 self.is_fatal_fn = Some(Box::new(f));
123 self
124 }
125}
126
127impl<T> ConnectionFactory<T> for FnFactory<T>
128where
129 T: Send + Sync,
130{
131 fn create(&self) -> Result<T, FactoryError> {
132 (self.create_fn)()
133 }
134
135 fn validate(&self, conn: &T) -> bool {
136 match &self.validate_fn {
137 Some(f) => f(conn),
138 None => true,
139 }
140 }
141
142 fn reset(&self, conn: &T) -> Result<(), FactoryError> {
143 match &self.reset_fn {
144 Some(f) => f(conn),
145 None => Ok(()),
146 }
147 }
148
149 fn close(&self, conn: &T) -> Result<(), FactoryError> {
150 match &self.close_fn {
151 Some(f) => f(conn),
152 None => Ok(()),
153 }
154 }
155
156 fn is_fatal_error(&self, err: &(dyn Error + 'static)) -> bool {
157 match &self.is_fatal_fn {
158 Some(f) => f(err),
159 None => false,
160 }
161 }
162}
163
164#[cfg(test)]
165mod tests {
166 use super::*;
167
168 #[test]
169 fn defaults_apply_when_unset() {
170 let f = FnFactory::new(|| Ok::<_, FactoryError>(7u32));
171 assert_eq!(f.create().unwrap(), 7);
172 assert!(f.validate(&7));
173 assert!(f.reset(&7).is_ok());
174 assert!(f.close(&7).is_ok());
175 let err: FactoryError = "x".into();
176 assert!(!f.is_fatal_error(&*err));
177 }
178
179 #[test]
180 fn custom_hooks_are_used() {
181 let f = FnFactory::new(|| Ok::<_, FactoryError>(1u32))
182 .with_validate(|c| *c == 1)
183 .with_reset(|_| Err::<(), FactoryError>("reset boom".into()))
184 .with_close(|_| Err::<(), FactoryError>("close boom".into()))
185 .with_is_fatal_error(|e| e.to_string() == "fatal");
186 assert!(f.validate(&1));
187 assert!(!f.validate(&2));
188 assert_eq!(f.reset(&1).unwrap_err().to_string(), "reset boom");
189 assert_eq!(f.close(&1).unwrap_err().to_string(), "close boom");
190 let fatal: FactoryError = "fatal".into();
191 let ok: FactoryError = "meh".into();
192 assert!(f.is_fatal_error(&*fatal));
193 assert!(!f.is_fatal_error(&*ok));
194 }
195
196 #[test]
197 fn create_can_fail() {
198 let f = FnFactory::new(|| Err::<u32, FactoryError>("down".into()));
199 assert_eq!(f.create().unwrap_err().to_string(), "down");
200 }
201
202 #[test]
203 fn trait_defaults_apply_to_a_minimal_impl() {
204 struct Minimal;
205 impl ConnectionFactory<u32> for Minimal {
206 fn create(&self) -> Result<u32, FactoryError> {
207 Ok(1)
208 }
209 }
210 let m = Minimal;
211 assert_eq!(m.create().unwrap(), 1);
212 assert!(m.validate(&1));
213 assert!(m.reset(&1).is_ok());
214 assert!(m.close(&1).is_ok());
215 let e: FactoryError = "x".into();
216 assert!(!m.is_fatal_error(&*e));
217 }
218
219 #[test]
220 fn boxed_factory_delegates() {
221 let boxed: Box<dyn ConnectionFactory<u32>> = Box::new(
222 FnFactory::new(|| Ok::<_, FactoryError>(5u32))
223 .with_validate(|c| *c == 5)
224 .with_reset(|_| Ok(()))
225 .with_close(|_| Ok(()))
226 .with_is_fatal_error(|_| true),
227 );
228 assert_eq!(boxed.create().unwrap(), 5);
229 assert!(boxed.validate(&5));
230 assert!(boxed.reset(&5).is_ok());
231 assert!(boxed.close(&5).is_ok());
232 let e: FactoryError = "x".into();
233 assert!(boxed.is_fatal_error(&*e));
234 }
235}