use r2d2::CustomizeConnection;
use r2d2_sqlite::SqliteConnectionManager;
use rusqlite::Connection;
use rust_ef::error::{EFError, EFResult};
use std::sync::Arc;
use tokio::sync::Mutex;
#[derive(Debug)]
pub(crate) struct SqliteConnectionCustomizer;
impl CustomizeConnection<Connection, rusqlite::Error> for SqliteConnectionCustomizer {
fn on_acquire(&self, conn: &mut Connection) -> Result<(), rusqlite::Error> {
conn.execute_batch("PRAGMA journal_mode=WAL; PRAGMA busy_timeout=5000;")
}
}
pub(crate) const SQLITE_DEFAULT_POOL_SIZE: u32 = 8;
pub(crate) enum SqliteProviderInner {
Pooled(r2d2::Pool<SqliteConnectionManager>),
Single(Arc<Mutex<rusqlite::Connection>>),
}
impl SqliteProviderInner {
pub(crate) async fn get_connection(
&self,
) -> EFResult<Box<dyn rust_ef::provider::IAsyncConnection>> {
match self {
SqliteProviderInner::Pooled(pool) => {
let conn = pool.get().map_err(|e| {
EFError::connection(format!("SQLite pool acquire failed: {}", e))
})?;
Ok(Box::new(crate::connection::SqliteConnection::new_pooled(
conn,
)))
}
SqliteProviderInner::Single(conn) => Ok(Box::new(
crate::connection::SqliteConnection::new_shared(Arc::clone(conn)),
)),
}
}
pub(crate) async fn execute_migration_command(&self, sql: &str) -> EFResult<()> {
match self {
SqliteProviderInner::Pooled(pool) => {
let conn = pool.get().map_err(|e| {
EFError::connection(format!("SQLite pool acquire failed: {}", e))
})?;
conn.execute_batch(sql).map_err(|e| {
EFError::migration(format!("Migration execution failed: {}", e))
})?;
Ok(())
}
SqliteProviderInner::Single(conn) => {
let guard = conn.lock().await;
guard.execute_batch(sql).map_err(|e| {
EFError::migration(format!("Migration execution failed: {}", e))
})?;
Ok(())
}
}
}
}