use std::{fmt, future::Future, sync::Arc};
use self::inner::PoolInner;
use crate::{
Error, Result, SqliteRuntimeInfo, WalCheckpoint, WalCheckpointMode, transaction::Transaction,
};
mod connection;
mod inner;
pub use self::connection::PoolConnection;
pub struct Pool(pub(crate) Arc<PoolInner>);
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct PoolStats {
pub size: u32,
pub num_idle: usize,
pub is_closed: bool,
}
impl Pool {
pub(crate) async fn new(options: crate::Musq) -> Result<Self> {
if options.pool_max_connections == 0 {
return Err(Error::Protocol("max_connections must be at least 1".into()));
}
let inner = PoolInner::new_arc(options);
let conn = inner.acquire().await?;
inner.release(conn);
Ok(Self(inner))
}
pub async fn acquire(&self) -> Result<PoolConnection> {
let shared = self.0.clone();
shared.acquire().await.map(|conn| conn.reattach())
}
pub fn try_acquire(&self) -> Option<PoolConnection> {
self.0.try_acquire().map(|conn| conn.into_live().reattach())
}
pub async fn begin(&self) -> Result<Transaction<PoolConnection>> {
Transaction::begin(self.acquire().await?).await
}
pub async fn runtime_info(&self) -> Result<SqliteRuntimeInfo> {
let conn = self.acquire().await?;
conn.runtime_info().await
}
pub async fn wal_checkpoint(
&self,
schema: Option<&str>,
mode: WalCheckpointMode,
) -> Result<WalCheckpoint> {
let conn = self.acquire().await?;
conn.wal_checkpoint(schema, mode).await
}
pub async fn try_begin(&self) -> Result<Option<Transaction<PoolConnection>>> {
match self.try_acquire() {
Some(conn) => Transaction::begin(conn).await.map(Some),
None => Ok(None),
}
}
#[must_use = "futures returned by `Pool::close` must be awaited"]
pub async fn close(&self) {
self.0.close().await
}
pub fn is_closed(&self) -> bool {
self.0.is_closed()
}
pub fn close_event(&self) -> impl Future<Output = ()> + '_ {
self.0.close_event()
}
pub fn size(&self) -> u32 {
self.0.size()
}
pub fn num_idle(&self) -> usize {
self.0.num_idle()
}
pub fn stats(&self) -> PoolStats {
PoolStats {
size: self.size(),
num_idle: self.num_idle(),
is_closed: self.is_closed(),
}
}
}
impl Clone for Pool {
fn clone(&self) -> Self {
Self(Arc::clone(&self.0))
}
}
impl fmt::Debug for Pool {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("Pool")
.field("size", &self.size())
.field("num_idle", &self.num_idle())
.field("is_closed", &self.0.is_closed())
.field("options", &self.0.options)
.finish()
}
}