tempo_cli/db/
mod.rs

1pub mod advanced_queries;
2pub mod connection;
3pub mod migrations;
4pub mod pool;
5pub mod queries;
6pub mod seed;
7
8use anyhow::Result;
9use std::path::Path;
10use std::sync::OnceLock;
11
12pub use connection::Database;
13pub use pool::{DatabasePool, PoolConfig, PooledConnectionGuard};
14
15/// Global database pool instance
16static DB_POOL: OnceLock<DatabasePool> = OnceLock::new();
17
18pub fn initialize_database(db_path: &Path) -> Result<Database> {
19    println!("Initializing database at: {:?}", db_path);
20    let db = Database::new(db_path)?;
21    println!("Database connection created");
22
23    // Run migrations
24    println!("Running migrations...");
25    migrations::run_migrations(&db.connection)?;
26    println!("Migrations completed");
27
28    Ok(db)
29}
30
31pub fn get_database_path() -> Result<std::path::PathBuf> {
32    let data_dir = dirs::data_dir()
33        .or_else(dirs::home_dir)
34        .ok_or_else(|| anyhow::anyhow!("Could not determine data directory"))?;
35
36    let tempo_dir = data_dir.join(".tempo");
37    std::fs::create_dir_all(&tempo_dir)?;
38
39    Ok(tempo_dir.join("data.db"))
40}
41
42/// Initialize the global database pool
43pub fn initialize_pool() -> Result<()> {
44    let db_path = get_database_path()?;
45    let pool = DatabasePool::new_with_defaults(db_path)?;
46
47    DB_POOL
48        .set(pool)
49        .map_err(|_| anyhow::anyhow!("Database pool already initialized"))?;
50
51    Ok(())
52}
53
54/// Initialize the global database pool with custom configuration
55pub fn initialize_pool_with_config(config: PoolConfig) -> Result<()> {
56    let db_path = get_database_path()?;
57    let pool = DatabasePool::new(db_path, config)?;
58
59    DB_POOL
60        .set(pool)
61        .map_err(|_| anyhow::anyhow!("Database pool already initialized"))?;
62
63    Ok(())
64}
65
66/// Get a connection from the global pool
67pub async fn get_connection() -> Result<PooledConnectionGuard> {
68    let pool = DB_POOL.get().ok_or_else(|| {
69        anyhow::anyhow!("Database pool not initialized. Call initialize_pool() first.")
70    })?;
71
72    pool.get_connection().await
73}
74
75/// Get pool statistics
76pub fn get_pool_stats() -> Result<pool::PoolStats> {
77    let pool = DB_POOL
78        .get()
79        .ok_or_else(|| anyhow::anyhow!("Database pool not initialized"))?;
80
81    pool.stats()
82}
83
84/// Close the global pool
85pub fn close_pool() -> Result<()> {
86    if let Some(pool) = DB_POOL.get() {
87        pool.close()?;
88    }
89    Ok(())
90}