deadpool_r2d2/
manager.rs

1use std::{fmt, sync::Arc};
2
3use deadpool::{
4    managed::{self, Metrics, RecycleError, RecycleResult},
5    Runtime,
6};
7use deadpool_sync::SyncWrapper;
8
9/// [`Manager`] for use with [`r2d2`] [managers](r2d2::ManageConnection).
10///
11/// See the [`deadpool` documentation](deadpool) for usage examples.
12///
13/// [`Manager`]: managed::Manager
14pub struct Manager<M: r2d2::ManageConnection> {
15    r2d2_manager: Arc<M>,
16    runtime: Runtime,
17}
18
19// Implemented manually to avoid unnecessary trait bound on `C` type parameter.
20impl<M: r2d2::ManageConnection> fmt::Debug for Manager<M>
21where
22    M: fmt::Debug,
23{
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        f.debug_struct("Manager")
26            .field("r2d2_manager", &self.r2d2_manager)
27            .field("runtime", &self.runtime)
28            .finish()
29    }
30}
31
32impl<M: r2d2::ManageConnection> Manager<M> {
33    /// Creates a new [`Manager`] using the given [`r2d2`] [manager](r2d2::ManageConnection)
34    #[must_use]
35    pub fn new(r2d2_manager: M, runtime: Runtime) -> Self {
36        Manager {
37            runtime,
38            r2d2_manager: Arc::new(r2d2_manager),
39        }
40    }
41}
42
43impl<M: r2d2::ManageConnection> managed::Manager for Manager<M>
44where
45    M::Error: Send,
46{
47    type Type = SyncWrapper<M::Connection>;
48    type Error = M::Error;
49
50    async fn create(&self) -> Result<Self::Type, Self::Error> {
51        let r2d2_manager = self.r2d2_manager.clone();
52        SyncWrapper::new(self.runtime, move || r2d2_manager.connect()).await
53    }
54
55    async fn recycle(&self, obj: &mut Self::Type, _: &Metrics) -> RecycleResult<Self::Error> {
56        if obj.is_mutex_poisoned() {
57            return Err(RecycleError::message(
58                "Mutex is poisoned. Connection is considered unusable.",
59            ));
60        }
61        let r2d2_manager = self.r2d2_manager.clone();
62        obj.interact::<_, RecycleResult<Self::Error>>(move |obj| {
63            if r2d2_manager.has_broken(obj) {
64                Err(RecycleError::message("Connection is broken"))
65            } else {
66                r2d2_manager.is_valid(obj).map_err(RecycleError::Backend)
67            }
68        })
69        .await
70        .map_err(|e| RecycleError::message(format!("Interaction failed: {}", e)))?
71    }
72}