Skip to main content

pool_mod/
manager.rs

1//! The [`Manager`] trait: how a pool creates, checks, and recycles its resources.
2
3/// Creates and maintains the resources held by a [`Pool`](crate::Pool).
4///
5/// Implement this for whatever you want to pool — a database connection, an HTTP
6/// client, a worker handle, or any other resource that is expensive to build. The
7/// pool drives the resource lifecycle through three hooks:
8///
9/// - [`create`](Manager::create) — build a new resource when the pool needs to
10///   grow toward `max_size`.
11/// - [`validate`](Manager::validate) — confirm an idle resource is still usable
12///   before lending it out (validation-on-borrow).
13/// - [`recycle`](Manager::recycle) — reset a returned resource so it can be lent
14///   out again.
15///
16/// One manager is shared across every thread that uses the pool, so it must be
17/// `Send + Sync`. The pool never holds its internal lock while calling these
18/// methods, so a slow `create` or `validate` does not block other threads from
19/// returning resources.
20///
21/// # Examples
22///
23/// A manager that pools reusable byte buffers:
24///
25/// ```
26/// use pool_mod::Manager;
27/// use std::convert::Infallible;
28///
29/// struct Buffers {
30///     capacity: usize,
31/// }
32///
33/// impl Manager for Buffers {
34///     type Resource = Vec<u8>;
35///     type Error = Infallible;
36///
37///     fn create(&self) -> Result<Vec<u8>, Infallible> {
38///         Ok(Vec::with_capacity(self.capacity))
39///     }
40///
41///     fn recycle(&self, buf: &mut Vec<u8>) -> Result<(), Infallible> {
42///         buf.clear(); // keep the allocation, drop the contents
43///         Ok(())
44///     }
45/// }
46/// ```
47pub trait Manager: Send + Sync + 'static {
48    /// The resource this manager produces and the pool hands out.
49    type Resource: Send + 'static;
50
51    /// The error returned when creating or recycling a resource fails.
52    ///
53    /// Use a domain error type for real backends. When a resource can never fail
54    /// to build, [`std::convert::Infallible`] is the honest choice.
55    type Error: Send + Sync + 'static;
56
57    /// Build a new resource.
58    ///
59    /// Called when the pool needs to grow toward `max_size`. Runs without the
60    /// pool's internal lock held, so a blocking constructor (opening a socket,
61    /// say) does not stall other threads.
62    ///
63    /// # Errors
64    ///
65    /// Returns [`Self::Error`] if the resource cannot be created. The pool
66    /// surfaces it as [`Error::Backend`](crate::Error::Backend) and releases the
67    /// slot it had reserved, so a failed creation does not permanently shrink the
68    /// pool.
69    fn create(&self) -> Result<Self::Resource, Self::Error>;
70
71    /// Reset a returned resource so it is fit to lend out again.
72    ///
73    /// Called when a borrowed resource is dropped back into the pool — roll back
74    /// an open transaction, clear a buffer, reset a cursor.
75    ///
76    /// # Errors
77    ///
78    /// Returns [`Self::Error`] if the resource cannot be made reusable. The pool
79    /// then discards it instead of returning it to the idle set, freeing the slot
80    /// for a fresh resource.
81    fn recycle(&self, resource: &mut Self::Resource) -> Result<(), Self::Error>;
82
83    /// Check that an idle resource is still usable before lending it out.
84    ///
85    /// Called on checkout for any resource taken from the idle set. Return
86    /// `false` to have the pool discard the resource and move on to the next idle
87    /// one — or to a freshly created resource if the idle set is exhausted.
88    ///
89    /// The default accepts every resource. Override it for validation-on-borrow,
90    /// such as pinging a connection to confirm the peer has not closed it.
91    ///
92    /// # Examples
93    ///
94    /// ```
95    /// use pool_mod::Manager;
96    /// use std::convert::Infallible;
97    ///
98    /// struct Sessions;
99    ///
100    /// impl Manager for Sessions {
101    ///     type Resource = (bool, u32); // (alive, id)
102    ///     type Error = Infallible;
103    ///
104    ///     fn create(&self) -> Result<(bool, u32), Infallible> {
105    ///         Ok((true, 0))
106    ///     }
107    ///
108    ///     fn recycle(&self, _s: &mut (bool, u32)) -> Result<(), Infallible> {
109    ///         Ok(())
110    ///     }
111    ///
112    ///     fn validate(&self, session: &mut (bool, u32)) -> bool {
113    ///         session.0 // only lend out sessions still marked alive
114    ///     }
115    /// }
116    /// ```
117    fn validate(&self, resource: &mut Self::Resource) -> bool {
118        let _ = resource;
119        true
120    }
121}