diesel_async/pooled_connection/bb8.rs
1//! A pool implementation for `diesel-async` based on [`bb8`]
2//!
3//! ```rust
4//! # include!("../doctest_setup.rs");
5//! use diesel::result::Error;
6//! use futures_util::FutureExt;
7//! use diesel_async::pooled_connection::AsyncDieselConnectionManager;
8//! use diesel_async::pooled_connection::bb8::Pool;
9//! use diesel_async::{RunQueryDsl, AsyncConnection};
10//!
11//! # #[tokio::main(flavor = "current_thread")]
12//! # async fn main() {
13//! # run_test().await.unwrap();
14//! # }
15//! #
16//! # #[cfg(feature = "postgres")]
17//! # fn get_config() -> AsyncDieselConnectionManager<diesel_async::AsyncPgConnection> {
18//! # let db_url = database_url_from_env("PG_DATABASE_URL");
19//! let config = AsyncDieselConnectionManager::<diesel_async::AsyncPgConnection>::new(db_url);
20//! # config
21//! # }
22//! #
23//! # #[cfg(feature = "mysql")]
24//! # fn get_config() -> AsyncDieselConnectionManager<diesel_async::AsyncMysqlConnection> {
25//! # let db_url = database_url_from_env("MYSQL_DATABASE_URL");
26//! # let config = AsyncDieselConnectionManager::<diesel_async::AsyncMysqlConnection>::new(db_url);
27//! # config
28//! # }
29//! #
30//! # #[cfg(feature = "sqlite")]
31//! # fn get_config() -> AsyncDieselConnectionManager<diesel_async::sync_connection_wrapper::SyncConnectionWrapper<diesel::SqliteConnection>> {
32//! # let db_url = database_url_from_env("SQLITE_DATABASE_URL");
33//! # let config = AsyncDieselConnectionManager::<diesel_async::sync_connection_wrapper::SyncConnectionWrapper<diesel::SqliteConnection>>::new(db_url);
34//! # config
35//! # }
36//! #
37//! # async fn run_test() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
38//! # use schema::users::dsl::*;
39//! # let config = get_config();
40//! # #[cfg(feature = "postgres")]
41//! let pool: Pool<AsyncPgConnection> = Pool::builder().build(config).await?;
42//! # #[cfg(not(feature = "postgres"))]
43//! # let pool = Pool::builder().build(config).await?;
44//! let mut conn = pool.get().await?;
45//! # conn.begin_test_transaction();
46//! # create_tables(&mut conn).await;
47//! # #[cfg(feature = "mysql")]
48//! # conn.begin_test_transaction();
49//! let res = users.load::<(i32, String)>(&mut conn).await?;
50//! # Ok(())
51//! # }
52//! ```
53
54use super::{AsyncDieselConnectionManager, PoolError, PoolableConnection};
55use bb8::ManageConnection;
56use diesel::query_builder::QueryFragment;
57
58/// Type alias for using [`bb8::Pool`] with [`diesel-async`]
59///
60/// This is **not** equal to [`bb8::Pool`]. It already uses the correct
61/// connection manager and expects only the connection type as generic argument
62pub type Pool<C> = bb8::Pool<AsyncDieselConnectionManager<C>>;
63/// Type alias for using [`bb8::PooledConnection`] with [`diesel-async`]
64pub type PooledConnection<'a, C> = bb8::PooledConnection<'a, AsyncDieselConnectionManager<C>>;
65/// Type alias for using [`bb8::RunError`] with [`diesel-async`]
66pub type RunError = bb8::RunError<super::PoolError>;
67
68#[async_trait::async_trait]
69impl<C> ManageConnection for AsyncDieselConnectionManager<C>
70where
71 C: PoolableConnection + 'static,
72 diesel::dsl::select<diesel::dsl::AsExprOf<i32, diesel::sql_types::Integer>>:
73 crate::methods::ExecuteDsl<C>,
74 diesel::query_builder::SqlQuery: QueryFragment<C::Backend>,
75{
76 type Connection = C;
77
78 type Error = PoolError;
79
80 async fn connect(&self) -> Result<Self::Connection, Self::Error> {
81 (self.manager_config.custom_setup)(&self.connection_url)
82 .await
83 .map_err(PoolError::ConnectionError)
84 }
85
86 async fn is_valid(&self, conn: &mut Self::Connection) -> Result<(), Self::Error> {
87 conn.ping(&self.manager_config.recycling_method)
88 .await
89 .map_err(PoolError::QueryError)
90 }
91
92 fn has_broken(&self, conn: &mut Self::Connection) -> bool {
93 std::thread::panicking() || conn.is_broken()
94 }
95}