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

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