deadpool/managed/
builder.rs
1use std::{fmt, marker::PhantomData, time::Duration};
2
3use crate::Runtime;
4
5use super::{
6 hooks::{Hook, Hooks},
7 Manager, Object, Pool, PoolConfig, Timeouts,
8};
9
10#[derive(Debug)]
13pub enum BuildError<E> {
14 Backend(E),
16
17 NoRuntimeSpecified(String),
19}
20
21impl<E: std::fmt::Display> fmt::Display for BuildError<E> {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 match self {
24 Self::Backend(e) => write!(f, "Error occurred while building the pool: Backend: {}", e),
25 Self::NoRuntimeSpecified(msg) => write!(
26 f,
27 "Error occurred while building the pool: NoRuntimeSpecified: {}",
28 msg
29 ),
30 }
31 }
32}
33
34impl<E: std::error::Error + 'static> std::error::Error for BuildError<E> {
35 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
36 match self {
37 Self::Backend(e) => Some(e),
38 Self::NoRuntimeSpecified(_) => None,
39 }
40 }
41}
42
43#[must_use = "builder does nothing itself, use `.build()` to build it"]
47pub struct PoolBuilder<M, W = Object<M>>
48where
49 M: Manager,
50 W: From<Object<M>>,
51{
52 pub(crate) manager: M,
53 pub(crate) config: PoolConfig,
54 pub(crate) runtime: Option<Runtime>,
55 pub(crate) hooks: Hooks<M>,
56 _wrapper: PhantomData<fn() -> W>,
57}
58
59impl<M, W> fmt::Debug for PoolBuilder<M, W>
61where
62 M: fmt::Debug + Manager,
63 W: From<Object<M>>,
64{
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 f.debug_struct("PoolBuilder")
67 .field("manager", &self.manager)
68 .field("config", &self.config)
69 .field("runtime", &self.runtime)
70 .field("hooks", &self.hooks)
71 .field("_wrapper", &self._wrapper)
72 .finish()
73 }
74}
75
76impl<M, W> PoolBuilder<M, W>
77where
78 M: Manager,
79 W: From<Object<M>>,
80{
81 pub(crate) fn new(manager: M) -> Self {
82 Self {
83 manager,
84 config: PoolConfig::default(),
85 runtime: None,
86 hooks: Hooks::default(),
87 _wrapper: PhantomData::default(),
88 }
89 }
90
91 pub fn build(self) -> Result<Pool<M, W>, BuildError<M::Error>> {
97 let t = &self.config.timeouts;
99 if (t.wait.is_some() || t.create.is_some() || t.recycle.is_some()) && self.runtime.is_none()
100 {
101 return Err(BuildError::NoRuntimeSpecified(
102 "Timeouts require a runtime".to_string(),
103 ));
104 }
105 Ok(Pool::from_builder(self))
106 }
107
108 pub fn config(mut self, value: PoolConfig) -> Self {
110 self.config = value;
111 self
112 }
113
114 pub fn max_size(mut self, value: usize) -> Self {
116 self.config.max_size = value;
117 self
118 }
119
120 pub fn timeouts(mut self, value: Timeouts) -> Self {
122 self.config.timeouts = value;
123 self
124 }
125
126 pub fn wait_timeout(mut self, value: Option<Duration>) -> Self {
128 self.config.timeouts.wait = value;
129 self
130 }
131
132 pub fn create_timeout(mut self, value: Option<Duration>) -> Self {
134 self.config.timeouts.create = value;
135 self
136 }
137
138 pub fn recycle_timeout(mut self, value: Option<Duration>) -> Self {
140 self.config.timeouts.recycle = value;
141 self
142 }
143
144 pub fn post_create(mut self, hook: impl Into<Hook<M>>) -> Self {
149 self.hooks.post_create.push(hook.into());
150 self
151 }
152
153 pub fn pre_recycle(mut self, hook: impl Into<Hook<M>>) -> Self {
158 self.hooks.pre_recycle.push(hook.into());
159 self
160 }
161
162 pub fn post_recycle(mut self, hook: impl Into<Hook<M>>) -> Self {
167 self.hooks.post_recycle.push(hook.into());
168 self
169 }
170
171 pub fn runtime(mut self, value: Runtime) -> Self {
186 self.runtime = Some(value);
187 self
188 }
189}