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}