burncloud_database_client/
client.rs1use burncloud_database_core::{
2 DatabaseConnection, QueryExecutor, TransactionManager, Transaction,
3 QueryContext, QueryOptions, QueryResult, QueryParam
4};
5use burncloud_database_core::error::{DatabaseResult, DatabaseError};
6use async_trait::async_trait;
7use std::sync::Arc;
8use tokio::sync::RwLock;
9use tracing::{info, error, debug};
10
11pub struct DatabaseClient {
12 connection: Arc<RwLock<Box<dyn DatabaseConnection>>>,
13 query_executor: Arc<Box<dyn QueryExecutor>>,
14}
15
16impl DatabaseClient {
17 pub fn new(
18 connection: Box<dyn DatabaseConnection>,
19 query_executor: Box<dyn QueryExecutor>,
20 ) -> Self {
21 Self {
22 connection: Arc::new(RwLock::new(connection)),
23 query_executor: Arc::new(query_executor),
24 }
25 }
26
27 pub async fn connect(&self) -> DatabaseResult<()> {
28 let mut conn = self.connection.write().await;
29 info!("Connecting to database...");
30 conn.connect().await?;
31 info!("Successfully connected to database");
32 Ok(())
33 }
34
35 pub async fn disconnect(&self) -> DatabaseResult<()> {
36 let mut conn = self.connection.write().await;
37 info!("Disconnecting from database...");
38 conn.disconnect().await?;
39 info!("Successfully disconnected from database");
40 Ok(())
41 }
42
43 pub async fn is_connected(&self) -> bool {
44 let conn = self.connection.read().await;
45 conn.is_connected().await
46 }
47
48 pub async fn ping(&self) -> DatabaseResult<()> {
49 let conn = self.connection.read().await;
50 debug!("Pinging database...");
51 conn.ping().await?;
52 debug!("Database ping successful");
53 Ok(())
54 }
55
56 pub async fn execute_query(
57 &self,
58 query: &str,
59 params: &[&dyn QueryParam],
60 context: &QueryContext,
61 ) -> DatabaseResult<QueryResult> {
62 debug!("Executing query: {}", query);
63 let result = self.query_executor.execute_query(query, params, context).await;
64
65 match &result {
66 Ok(res) => debug!("Query executed successfully, {} rows returned", res.rows.len()),
67 Err(e) => error!("Query execution failed: {}", e),
68 }
69
70 result
71 }
72
73 pub async fn execute_query_with_options(
74 &self,
75 query: &str,
76 params: &[&dyn QueryParam],
77 options: &QueryOptions,
78 context: &QueryContext,
79 ) -> DatabaseResult<QueryResult> {
80 debug!("Executing query with options: {}", query);
81 let result = self.query_executor.execute_query_with_options(query, params, options, context).await;
82
83 match &result {
84 Ok(res) => debug!("Query with options executed successfully, {} rows returned", res.rows.len()),
85 Err(e) => error!("Query with options execution failed: {}", e),
86 }
87
88 result
89 }
90}
91
92#[async_trait]
93impl DatabaseConnection for DatabaseClient {
94 async fn connect(&mut self) -> DatabaseResult<()> {
95 self.connect().await
96 }
97
98 async fn disconnect(&mut self) -> DatabaseResult<()> {
99 self.disconnect().await
100 }
101
102 async fn is_connected(&self) -> bool {
103 self.is_connected().await
104 }
105
106 async fn ping(&self) -> DatabaseResult<()> {
107 self.ping().await
108 }
109}
110
111#[async_trait]
112impl QueryExecutor for DatabaseClient {
113 async fn execute_query(
114 &self,
115 query: &str,
116 params: &[&dyn QueryParam],
117 context: &QueryContext,
118 ) -> DatabaseResult<QueryResult> {
119 self.execute_query(query, params, context).await
120 }
121
122 async fn execute_query_with_options(
123 &self,
124 query: &str,
125 params: &[&dyn QueryParam],
126 options: &QueryOptions,
127 context: &QueryContext,
128 ) -> DatabaseResult<QueryResult> {
129 self.execute_query_with_options(query, params, options, context).await
130 }
131}