use crate::error::{Result, TidewayError};
use crate::traits::database::{DatabaseConnection, DatabasePool};
use async_trait::async_trait;
use sea_orm::{ConnectOptions, Database, DatabaseConnection as SeaOrmConnection};
use std::sync::Arc;
use std::time::Duration;
pub struct SeaOrmConnectionWrapper {
pub conn: SeaOrmConnection,
}
impl DatabaseConnection for SeaOrmConnectionWrapper {
fn is_valid(&self) -> bool {
true
}
}
impl std::ops::Deref for SeaOrmConnectionWrapper {
type Target = SeaOrmConnection;
fn deref(&self) -> &Self::Target {
&self.conn
}
}
pub struct SeaOrmPool {
conn: Arc<SeaOrmConnection>,
url: String,
}
impl SeaOrmPool {
pub fn new(conn: SeaOrmConnection, url: String) -> Self {
Self {
conn: Arc::new(conn),
url,
}
}
pub async fn from_config(config: &crate::database::DatabaseConfig) -> Result<Self> {
let mut opt = ConnectOptions::new(&config.url);
opt.max_connections(config.max_connections)
.min_connections(config.min_connections)
.connect_timeout(Duration::from_secs(config.connect_timeout))
.idle_timeout(Duration::from_secs(config.idle_timeout))
.sqlx_logging(true);
let conn = Database::connect(opt)
.await
.map_err(|e| TidewayError::internal(format!("Failed to connect to database: {}", e)))?;
tracing::info!(
"Database connected with {} max connections",
config.max_connections
);
Ok(Self::new(conn, config.url.clone()))
}
pub fn as_ref(&self) -> &SeaOrmConnection {
&self.conn
}
}
#[async_trait]
impl DatabasePool for SeaOrmPool {
async fn connection(&self) -> Result<Box<dyn DatabaseConnection>> {
Ok(Box::new(SeaOrmConnectionWrapper {
conn: (*self.conn).clone(),
}))
}
fn is_healthy(&self) -> bool {
true
}
async fn close(self: Box<Self>) -> Result<()> {
drop(self);
Ok(())
}
fn connection_url(&self) -> Option<&str> {
Some(&self.url)
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}