1use crate::config::DbConfig;
3use crate::error::DbResult;
4use sqlx::any::AnyPoolOptions;
5use sqlx::{AnyPool, Connection};
6use std::sync::Arc;
7use tracing::{debug, info};
8
9#[derive(Clone, Debug)]
10pub struct DbClient {
11 pub pool: Arc<AnyPool>,
12 pub config: Arc<DbConfig>,
13}
14
15impl DbClient {
16 pub async fn new(config: DbConfig) -> DbResult<Self> {
17 info!("Initializing DbClient with config: {:?}", config.db_type);
18 let cs = config.build_connection_string()?;
19 debug!("Constructed connection string: [REDACTED]");
20
21 let pool_options = if let Some(pool_config) = &config.pool_options {
22 AnyPoolOptions::new()
23 .max_connections(pool_config.max_connections.unwrap_or(5))
24 .min_connections(pool_config.min_connections.unwrap_or(1))
25 } else {
27 AnyPoolOptions::new()
28 };
29
30 debug!("Connecting to database with type: {:?}", config.db_type);
31 let pool = pool_options.connect(&cs).await?;
32 info!(
33 "Successfully connected to database: {:?}",
34 config.database_name.as_deref().unwrap_or("default")
35 );
36
37 Ok(Self {
38 pool: Arc::new(pool),
39 config: Arc::new(config),
40 })
41 }
42
43 pub async fn test_connection(&self) -> DbResult<()> {
44 info!("Pinging database...");
45 let mut conn = self.pool.acquire().await?;
46 conn.ping().await?;
47 info!("Database ping successful.");
48 Ok(())
49 }
50
51 pub async fn get_db_version(&self) -> DbResult<String> {
52 debug!("Fetching database version...");
53 let query = match self.config.db_type {
54 _ => "SELECT version()",
56 };
57 let (version,): (String,) = sqlx::query_as(query).fetch_one(&*self.pool).await?;
58 debug!("Database version: {}", version);
59 Ok(version)
60 }
61}