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

1use std::ops::Deref;
2
3use async_trait::async_trait;
4use bb8::{Builder, Pool, PooledConnection, RunError};
5use bb8_postgres::PostgresConnectionManager;
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 = PostgresConnectionManager<NoTls>;
16
17/// [`tokio-postgres bb8`](https://docs.rs/bb8-postgres/0.8.1/bb8_postgres/) association
18/// # Example
19/// ```
20/// use bb8::Pool;
21/// use db_pool::r#async::{TokioPostgresBackend, TokioPostgresBb8};
22/// use tokio_postgres::Config;
23///
24/// async fn f() {
25///     let backend = TokioPostgresBackend::<TokioPostgresBb8>::new(
26///         "host=localhost user=postgres password=postgres"
27///             .parse::<Config>()
28///             .unwrap(),
29///         |_| Pool::builder().max_size(10),
30///         |_| Pool::builder().max_size(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 TokioPostgresBb8;
50
51#[async_trait]
52impl TokioPostgresPoolAssociation for TokioPostgresBb8 {
53    type PooledConnection<'pool> = PooledConnection<'pool, 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<Pool<Manager>, BuildError> {
65        let manager = Manager::new(config, NoTls);
66        builder.build(manager).await.map_err(Into::into)
67    }
68
69    async fn get_connection<'pool>(
70        pool: &'pool Self::Pool,
71    ) -> Result<Self::PooledConnection<'pool>, Self::PoolError> {
72        pool.get().await.map_err(Into::into)
73    }
74}
75
76#[derive(Debug)]
77pub struct BuildError(Error);
78
79impl Deref for BuildError {
80    type Target = Error;
81
82    fn deref(&self) -> &Self::Target {
83        &self.0
84    }
85}
86
87impl From<Error> for BuildError {
88    fn from(value: Error) -> Self {
89        Self(value)
90    }
91}
92
93#[derive(Debug)]
94pub struct PoolError(RunError<Error>);
95
96impl Deref for PoolError {
97    type Target = RunError<Error>;
98
99    fn deref(&self) -> &Self::Target {
100        &self.0
101    }
102}
103
104impl From<RunError<Error>> for PoolError {
105    fn from(value: RunError<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}