dbnexus/database/pool/
mod.rs1mod db_pool;
11mod session;
12
13#[cfg(feature = "duckdb")]
14pub mod duckdb_conn;
15
16use crate::foundation::config::DbConfig;
17
18pub use db_pool::{DatabaseConnection, DbConnection, DbPool, PoolStatus};
19pub use session::Session;
20
21#[cfg(feature = "duckdb")]
22pub use duckdb_conn::{DuckDbConnection, DuckDbExecResult, DuckDbRow};
23
24#[cfg(feature = "migration")]
26pub(crate) use crate::database::migration::MigrationExecutor;
27
28#[cfg(feature = "metrics")]
30use crate::observability::metrics::MetricsCollectorTrait;
31
32pub use sea_orm::{ConnectionTrait, TransactionTrait};
34
35use crate::foundation::error::DbResult;
36use async_trait::async_trait;
37use sea_orm::ExecResult;
38
39#[cfg(any(feature = "metrics", feature = "cache"))]
40use std::sync::Arc;
41
42#[cfg(feature = "cache")]
43use oxcache::Cache;
44
45#[async_trait]
49pub trait ConnectionPool: Send + Sync {
50 async fn get_session(&self, role: &str) -> DbResult<Session>;
60
61 fn status(&self) -> PoolStatus;
67
68 fn config(&self) -> &DbConfig;
74}
75
76#[async_trait]
80pub trait DatabaseSession: Send + Sync {
81 async fn execute(&self, sql: &str) -> DbResult<ExecResult>;
91
92 async fn execute_raw(&self, sql: &str) -> DbResult<ExecResult>;
102
103 async fn execute_raw_ddl(&self, sql: &str) -> DbResult<ExecResult>;
113
114 async fn begin_transaction(&self) -> DbResult<()>;
120
121 async fn commit(&self) -> DbResult<()>;
127
128 async fn rollback(&self) -> DbResult<()>;
134
135 fn role(&self) -> &str;
141
142 async fn is_in_transaction(&self) -> bool;
148}
149
150#[cfg(feature = "permission")]
155use crate::access::permission::PermissionConfig;
156#[cfg(feature = "metrics")]
157use crate::observability::metrics::MetricsCollector;
158
159#[derive(Clone, Default)]
180pub struct DbPoolBuilder {
181 url: Option<String>,
183 config: Option<DbConfig>,
185 #[cfg(feature = "metrics")]
187 metrics_collector: Option<Arc<dyn MetricsCollectorTrait>>,
188 #[cfg(feature = "permission")]
190 permission_config: Option<PermissionConfig>,
191 admin_role: Option<String>,
193 #[cfg(feature = "cache")]
195 cache: Option<Arc<Cache<String, serde_json::Value>>>,
196}
197
198impl DbPoolBuilder {
199 pub fn new() -> Self {
201 Self::default()
202 }
203
204 pub fn url(mut self, url: &str) -> Self {
214 self.url = Some(url.to_string());
215 self
216 }
217
218 pub fn config(mut self, config: DbConfig) -> Self {
228 self.config = Some(config);
229 self
230 }
231
232 #[deprecated(
239 since = "0.3.0",
240 note = "DbPoolBuilder::build() 静默丢弃此值;请通过 DbConfig 或 DbPool::with_config() 后注入"
241 )]
242 #[cfg(feature = "metrics")]
243 pub fn metrics_collector(mut self, metrics_collector: Arc<MetricsCollector>) -> Self {
244 self.metrics_collector = Some(metrics_collector);
245 self
246 }
247
248 #[deprecated(
255 since = "0.3.0",
256 note = "DbPoolBuilder::build() 静默丢弃此值;请使用 DbConfig.permission_config_path"
257 )]
258 #[cfg(feature = "permission")]
259 pub fn permission_config(mut self, permission_config: PermissionConfig) -> Self {
260 self.permission_config = Some(permission_config);
261 self
262 }
263
264 pub fn admin_role(mut self, admin_role: &str) -> Self {
274 if let Some(ref mut config) = self.config {
275 config.admin_role = admin_role.to_string();
276 } else {
277 self.admin_role = Some(admin_role.to_string());
278 }
279 self
280 }
281
282 #[deprecated(
289 since = "0.3.0",
290 note = "DbPoolBuilder::build() 静默丢弃此值;缓存由 DbPool::with_config() 根据 DbConfig.cache_config 自动创建"
291 )]
292 #[cfg(feature = "cache")]
293 pub fn with_oxcache(mut self, cache: Arc<Cache<String, serde_json::Value>>) -> Self {
294 self.cache = Some(cache);
295 self
296 }
297
298 pub fn max_connections(mut self, max_connections: u32) -> Self {
308 if let Some(ref mut config) = self.config {
309 config.max_connections = max_connections;
310 } else if let Some(ref url) = self.url {
311 let config = DbConfig {
313 url: url.clone(),
314 max_connections,
315 ..Default::default()
316 };
317 self.config = Some(config);
318 }
319 self
320 }
321
322 pub fn min_connections(mut self, min_connections: u32) -> Self {
332 if let Some(ref mut config) = self.config {
333 config.min_connections = min_connections;
334 } else if let Some(ref url) = self.url {
335 let config = DbConfig {
336 url: url.clone(),
337 min_connections,
338 ..Default::default()
339 };
340 self.config = Some(config);
341 }
342 self
343 }
344
345 pub async fn build(self) -> DbResult<DbPool> {
355 let config = if let Some(config) = self.config {
357 config
358 } else if let Some(url) = self.url {
359 DbConfig {
361 url,
362 max_connections: 20,
363 min_connections: 5,
364 idle_timeout: 300,
365 acquire_timeout: 5000,
366 admin_role: self.admin_role.unwrap_or_else(|| "admin".to_string()),
367 ..Default::default()
368 }
369 } else {
370 return Err(crate::foundation::error::DbError::new(sea_orm::DbErr::Custom(
371 "Either url or config must be provided".to_string(),
372 )));
373 };
374
375 let pool = DbPool::with_config(config).await?;
377
378 Ok(pool)
384 }
385}
386
387impl std::fmt::Debug for DbPoolBuilder {
388 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
389 f.debug_struct("DbPoolBuilder")
390 .field("url", &self.url)
391 .field("config", &self.config.is_some())
392 .field("admin_role", &self.admin_role)
393 .finish()
394 }
395}