use sea_orm::{ConnectOptions, Database, DatabaseConnection};
use std::sync::Arc;
use std::time::Duration;
use crate::database::config::DatabaseConfig;
use crate::error::FrameworkError;
#[derive(Clone)]
pub struct DbConnection {
inner: Arc<DatabaseConnection>,
}
impl DbConnection {
pub async fn connect(config: &DatabaseConfig) -> Result<Self, FrameworkError> {
let url = if config.url.starts_with("sqlite://") {
let path = config.url.trim_start_matches("sqlite://");
let path = path.trim_start_matches("./");
if path != ":memory:" && !path.starts_with(":memory:") {
if let Some(parent) = std::path::Path::new(path).parent() {
if !parent.as_os_str().is_empty() {
std::fs::create_dir_all(parent).ok();
}
}
if !std::path::Path::new(path).exists() {
std::fs::File::create(path).ok();
}
}
format!("sqlite:{path}?mode=rwc")
} else {
config.url.clone()
};
let mut opt = ConnectOptions::new(&url);
opt.max_connections(config.max_connections)
.min_connections(config.min_connections)
.connect_timeout(Duration::from_secs(config.connect_timeout))
.sqlx_logging(config.logging);
let conn = Database::connect(opt)
.await
.map_err(|e| FrameworkError::database(e.to_string()))?;
Ok(Self {
inner: Arc::new(conn),
})
}
pub fn inner(&self) -> &DatabaseConnection {
&self.inner
}
pub fn conn(&self) -> &DatabaseConnection {
&self.inner
}
pub fn is_closed(&self) -> bool {
false
}
}
impl AsRef<DatabaseConnection> for DbConnection {
fn as_ref(&self) -> &DatabaseConnection {
&self.inner
}
}
impl std::ops::Deref for DbConnection {
type Target = DatabaseConnection;
fn deref(&self) -> &Self::Target {
&self.inner
}
}