use crate::config;
use crate::sea_orm::{ConnectOptions, Database, DatabaseConnection, DbErr};
use std::sync::OnceLock;
static POOL: OnceLock<DatabaseConnection> = OnceLock::new();
fn options(url: &str, sql_logging: bool) -> ConnectOptions {
pool_options(url, sql_logging, None, None)
}
pub fn pool_options(
url: &str,
sql_logging: bool,
max_connections: Option<u32>,
connect_timeout_secs: Option<u64>,
) -> ConnectOptions {
let mut opts = ConnectOptions::new(url.to_owned());
opts.sqlx_logging(sql_logging);
if let Some(max) = max_connections {
opts.max_connections(max);
}
if let Some(secs) = connect_timeout_secs {
opts.connect_timeout(std::time::Duration::from_secs(secs));
}
opts
}
pub async fn connect() -> Result<DatabaseConnection, DbErr> {
let config = config::load();
let db = config.database();
Database::connect(pool_options(
db.url.as_str(),
config.logger().sql,
db.pool,
db.connect_timeout,
))
.await
}
pub async fn connect_with_url(url: &str) -> Result<DatabaseConnection, DbErr> {
Database::connect(options(url, true)).await
}
pub async fn init() -> Result<&'static DatabaseConnection, DbErr> {
if let Some(existing) = POOL.get() {
return Ok(existing);
}
let conn = connect().await?;
let _ = POOL.set(conn);
Ok(POOL.get().expect("pool was just set"))
}
pub fn set_pool(conn: DatabaseConnection) -> Result<(), DatabaseConnection> {
POOL.set(conn)
}
pub fn pool() -> &'static DatabaseConnection {
POOL.get().expect(
"database pool not initialised; call doido_model::pool::init() at boot before handling requests",
)
}
pub fn try_pool() -> Option<&'static DatabaseConnection> {
POOL.get()
}
pub fn test_lock() -> std::sync::MutexGuard<'static, ()> {
static LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
LOCK.lock().unwrap_or_else(|e| e.into_inner())
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn set_pool_then_pool_returns_it() {
assert!(try_pool().is_none());
let conn = connect_with_url("sqlite::memory:").await.unwrap();
set_pool(conn).expect("first install succeeds");
assert!(try_pool().is_some());
let _ = pool();
let second = connect_with_url("sqlite::memory:").await.unwrap();
assert!(set_pool(second).is_err());
}
}