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

1use std::ops::Deref;
2
3use async_trait::async_trait;
4use mobc::{Builder, Connection, Error as MobcError, Pool};
5use mobc_postgres::PgConnectionManager;
6use tokio_postgres::{Config, Error, NoTls};
7
8use crate::r#async::backend::{
9    common::error::tokio_postgres::{ConnectionError, QueryError},
10    error::Error as BackendError,
11};
12
13use super::r#trait::TokioPostgresPoolAssociation;
14
15type Manager = PgConnectionManager<NoTls>;
16
17/// [`tokio-postgres mobc`](https://docs.rs/mobc-postgres/0.8.0/mobc_postgres/) association
18/// # Example
19/// ```
20/// use db_pool::r#async::{TokioPostgresBackend, TokioPostgresMobc};
21/// use mobc::Pool;
22/// use tokio_postgres::Config;
23///
24/// async fn f() {
25///     let backend = TokioPostgresBackend::<TokioPostgresMobc>::new(
26///         "host=localhost user=postgres password=postgres"
27///             .parse::<Config>()
28///             .unwrap(),
29///         |_| Pool::builder().max_open(10),
30///         |_| Pool::builder().max_open(2),
31///         move |conn| {
32///             Box::pin(async move {
33///                 conn.execute(
34///                     "CREATE TABLE book(id SERIAL PRIMARY KEY, title TEXT NOT NULL)",
35///                     &[],
36///                 )
37///                 .await
38///                 .unwrap();
39///                 conn
40///             })
41///         },
42///     )
43///     .await
44///     .unwrap();
45/// }
46///
47/// tokio_test::block_on(f());
48/// ```
49pub struct TokioPostgresMobc;
50
51#[async_trait]
52impl TokioPostgresPoolAssociation for TokioPostgresMobc {
53    type PooledConnection<'pool> = Connection<Manager>;
54
55    type Builder = Builder<Manager>;
56    type Pool = Pool<Manager>;
57
58    type BuildError = BuildError;
59    type PoolError = PoolError;
60
61    async fn build_pool(
62        builder: Builder<Manager>,
63        config: Config,
64    ) -> Result<Self::Pool, Self::BuildError> {
65        let manager = Manager::new(config, NoTls);
66        Ok(builder.build(manager))
67    }
68
69    async fn get_connection<'pool>(
70        pool: &'pool Self::Pool,
71    ) -> Result<Connection<Manager>, PoolError> {
72        pool.get().await.map_err(Into::into)
73    }
74}
75
76#[derive(Debug)]
77pub struct BuildError(MobcError<Error>);
78
79impl Deref for BuildError {
80    type Target = MobcError<Error>;
81
82    fn deref(&self) -> &Self::Target {
83        &self.0
84    }
85}
86
87impl From<MobcError<Error>> for BuildError {
88    fn from(value: MobcError<Error>) -> Self {
89        Self(value)
90    }
91}
92
93#[derive(Debug)]
94pub struct PoolError(MobcError<Error>);
95
96impl Deref for PoolError {
97    type Target = MobcError<Error>;
98
99    fn deref(&self) -> &Self::Target {
100        &self.0
101    }
102}
103
104impl From<MobcError<Error>> for PoolError {
105    fn from(value: MobcError<Error>) -> Self {
106        Self(value)
107    }
108}
109
110impl From<BuildError> for BackendError<BuildError, PoolError, ConnectionError, QueryError> {
111    fn from(value: BuildError) -> Self {
112        Self::Build(value)
113    }
114}
115
116impl From<PoolError> for BackendError<BuildError, PoolError, ConnectionError, QueryError> {
117    fn from(value: PoolError) -> Self {
118        Self::Pool(value)
119    }
120}