db_pool/async/backend/common/pool/diesel/
mobc.rs

1use std::ops::{Deref, DerefMut};
2
3use async_trait::async_trait;
4use diesel::{ConnectionError, result::Error as DieselError};
5use diesel_async::{
6    AsyncConnection,
7    pooled_connection::{AsyncDieselConnectionManager, PoolError as DieselPoolError},
8};
9use mobc::{
10    Builder, Connection as MobcConnection, Error as MobcError, Manager as MobcManager, Pool,
11};
12
13use crate::r#async::backend::error::Error as BackendError;
14
15use super::r#trait::DieselPoolAssociation;
16
17type DieselManager<Connection> = AsyncDieselConnectionManager<Connection>;
18
19/// [`Diesel mobc`](https://docs.rs/diesel-async/0.5.2/diesel_async/pooled_connection/mobc/index.html) association
20/// # Example
21/// ```
22/// use db_pool::{
23///     r#async::{DieselAsyncPostgresBackend, DieselMobc},
24///     PrivilegedPostgresConfig,
25/// };
26/// use diesel::sql_query;
27/// use diesel_async::RunQueryDsl;
28/// use dotenvy::dotenv;
29/// use mobc::Pool;
30///
31/// async fn f() {
32///     dotenv().ok();
33///
34///     let config = PrivilegedPostgresConfig::from_env().unwrap();
35///
36///     let backend = DieselAsyncPostgresBackend::<DieselMobc>::new(
37///         config,
38///         |_| Pool::builder().max_open(10),
39///         |_| Pool::builder().max_open(2),
40///         None,
41///         move |mut conn| {
42///             Box::pin(async {
43///                 sql_query("CREATE TABLE book(id SERIAL PRIMARY KEY, title TEXT NOT NULL)")
44///                     .execute(&mut conn)
45///                     .await
46///                     .unwrap();
47///                 Some(conn)
48///             })
49///         },
50///     )
51///     .await
52///     .unwrap();
53/// }
54///
55/// tokio_test::block_on(f());
56/// ```
57pub struct DieselMobc;
58
59#[async_trait]
60impl<Connection> DieselPoolAssociation<Connection> for DieselMobc
61where
62    Connection: AsyncConnection + 'static,
63    DieselManager<Connection>: MobcManager,
64    for<'pool> MobcConnection<DieselManager<Connection>>: DerefMut<Target = Connection>,
65    MobcError<<DieselManager<Connection> as MobcManager>::Error>: Into<MobcError<DieselPoolError>>,
66{
67    type PooledConnection<'pool> = MobcConnection<DieselManager<Connection>>;
68
69    type Builder = Builder<DieselManager<Connection>>;
70    type Pool = Pool<DieselManager<Connection>>;
71
72    type BuildError = BuildError;
73    type PoolError = PoolError;
74
75    async fn build_pool(
76        builder: Builder<DieselManager<Connection>>,
77        manager: DieselManager<Connection>,
78    ) -> Result<Self::Pool, Self::BuildError> {
79        Ok(builder.build(manager))
80    }
81
82    async fn get_connection<'pool>(
83        pool: &'pool Self::Pool,
84    ) -> Result<Self::PooledConnection<'pool>, Self::PoolError> {
85        pool.get().await.map_err(|err| err.into().into())
86    }
87}
88
89#[derive(Debug)]
90pub struct BuildError(MobcError<DieselPoolError>);
91
92impl Deref for BuildError {
93    type Target = MobcError<DieselPoolError>;
94
95    fn deref(&self) -> &Self::Target {
96        &self.0
97    }
98}
99
100impl From<MobcError<DieselPoolError>> for BuildError {
101    fn from(value: MobcError<DieselPoolError>) -> Self {
102        Self(value)
103    }
104}
105
106#[derive(Debug)]
107pub struct PoolError(MobcError<DieselPoolError>);
108
109impl Deref for PoolError {
110    type Target = MobcError<DieselPoolError>;
111
112    fn deref(&self) -> &Self::Target {
113        &self.0
114    }
115}
116
117impl From<MobcError<DieselPoolError>> for PoolError {
118    fn from(value: MobcError<DieselPoolError>) -> Self {
119        Self(value)
120    }
121}
122
123impl From<BuildError> for BackendError<BuildError, PoolError, ConnectionError, DieselError> {
124    fn from(value: BuildError) -> Self {
125        Self::Build(value)
126    }
127}
128
129impl From<PoolError> for BackendError<BuildError, PoolError, ConnectionError, DieselError> {
130    fn from(value: PoolError) -> Self {
131        Self::Pool(value)
132    }
133}