use std::sync::Arc;
use super::{
backend::{r#trait::Backend, Error},
conn_pool::{ReusableConnectionPool as ReusableConnectionPoolInner, SingleUseConnectionPool},
object_pool::{ObjectPool, Reusable},
};
pub type ReusableConnectionPool<'a, B> = Reusable<'a, ReusableConnectionPoolInner<B>>;
pub struct DatabasePool<B: Backend> {
backend: Arc<B>,
object_pool: ObjectPool<ReusableConnectionPoolInner<B>>,
}
impl<B: Backend> DatabasePool<B> {
#[must_use]
pub fn pull_immutable(&self) -> Reusable<ReusableConnectionPoolInner<B>> {
self.object_pool.pull()
}
pub fn create_mutable(
&self,
) -> Result<SingleUseConnectionPool<B>, Error<B::ConnectionError, B::QueryError>> {
SingleUseConnectionPool::new(self.backend.clone())
}
}
pub trait DatabasePoolBuilder: Backend {
fn create_database_pool(
self,
) -> Result<DatabasePool<Self>, Error<Self::ConnectionError, Self::QueryError>> {
self.init()?;
let backend = Arc::new(self);
let object_pool = {
let backend = backend.clone();
ObjectPool::new(
move || {
let backend = backend.clone();
ReusableConnectionPoolInner::new(backend)
.expect("connection pool creation must succeed")
},
|conn_pool| {
conn_pool
.clean()
.expect("connection pool cleaning must succeed");
},
)
};
Ok(DatabasePool {
backend,
object_pool,
})
}
}
impl<B> DatabasePoolBuilder for B where B: Backend + Sized {}