parent
722e7af3e2
commit
750cf8d4ee
2 changed files with 16 additions and 15 deletions
|
|
@ -10,7 +10,7 @@ use sqlx::{ConnectOptions, sqlite::SqliteConnectOptions, types::chrono::Utc};
|
|||
|
||||
pub mod models;
|
||||
use sqlx::{Pool, Sqlite, sqlite::SqlitePoolOptions};
|
||||
use tokio::sync::RwLock;
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::time::Instant;
|
||||
use uuid::fmt::Hyphenated;
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ impl std::fmt::Debug for PoolWithTimestamp {
|
|||
pub struct Database {
|
||||
config: DatabaseConfig,
|
||||
broadcasts: Broadcasts,
|
||||
connection_pools: Arc<RwLock<HashMap<VaultId, PoolWithTimestamp>>>,
|
||||
connection_pools: Arc<Mutex<HashMap<VaultId, PoolWithTimestamp>>>,
|
||||
}
|
||||
|
||||
pub type Transaction<'a> = sqlx::Transaction<'a, Sqlite>;
|
||||
|
|
@ -83,7 +83,7 @@ impl Database {
|
|||
|
||||
let database = Self {
|
||||
config: config.clone(),
|
||||
connection_pools: Arc::new(RwLock::new(connection_pools)),
|
||||
connection_pools: Arc::new(Mutex::new(connection_pools)),
|
||||
broadcasts: broadcasts.clone(),
|
||||
};
|
||||
|
||||
|
|
@ -130,12 +130,11 @@ impl Database {
|
|||
}
|
||||
|
||||
async fn get_connection_pool(&self, vault: &VaultId) -> Result<Pool<Sqlite>> {
|
||||
// Fast path: check if pool exists with a read lock (no blocking other readers)
|
||||
// First, check if the pool exists without holding the lock during creation
|
||||
{
|
||||
let pools = self.connection_pools.read().await;
|
||||
if let Some(pool_with_timestamp) = pools.get(vault) {
|
||||
// Skip updating last_accessed here - it's only used for idle cleanup
|
||||
// and will be updated when the pool is created or reused after recreation
|
||||
let mut pools = self.connection_pools.lock().await;
|
||||
if let Some(pool_with_timestamp) = pools.get_mut(vault) {
|
||||
pool_with_timestamp.last_accessed = Instant::now();
|
||||
return Ok(pool_with_timestamp.pool.clone());
|
||||
}
|
||||
}
|
||||
|
|
@ -145,8 +144,8 @@ impl Database {
|
|||
// under high concurrency, but only one will be kept
|
||||
let new_pool = Self::create_vault_database(&self.config, vault).await?;
|
||||
|
||||
// Re-acquire lock (write) and insert (or use existing if another task created it)
|
||||
let mut pools = self.connection_pools.write().await;
|
||||
// Re-acquire lock and insert (or use existing if another task created it)
|
||||
let mut pools = self.connection_pools.lock().await;
|
||||
let pool_with_timestamp = pools
|
||||
.entry(vault.clone())
|
||||
.or_insert_with(|| PoolWithTimestamp {
|
||||
|
|
@ -481,19 +480,22 @@ impl Database {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Cleanup idle connection pools that haven't been accessed in more than 5 minutes
|
||||
async fn cleanup_idle_pools(&self) {
|
||||
use crate::consts::IDLE_POOL_TIMEOUT;
|
||||
|
||||
let mut pools = self.connection_pools.write().await;
|
||||
let mut pools = self.connection_pools.lock().await;
|
||||
let now = Instant::now();
|
||||
let idle_timeout = Duration::from_secs(5 * 60); // 5 minutes
|
||||
|
||||
// Collect vaults to remove
|
||||
let vaults_to_remove: Vec<VaultId> = pools
|
||||
.iter()
|
||||
.filter(|(_, pool_with_timestamp)| {
|
||||
now.duration_since(pool_with_timestamp.last_accessed) > IDLE_POOL_TIMEOUT
|
||||
now.duration_since(pool_with_timestamp.last_accessed) > idle_timeout
|
||||
})
|
||||
.map(|(vault_id, _)| vault_id.clone())
|
||||
.collect();
|
||||
|
||||
// Close and remove idle pools
|
||||
for vault_id in &vaults_to_remove {
|
||||
if let Some(pool_with_timestamp) = pools.remove(vault_id) {
|
||||
info!("Closing idle database connection pool for vault `{vault_id}`");
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ pub const DEFAULT_CONFIG_PATH: &str = "config.yml";
|
|||
pub const DEFAULT_DATABASES_DIRECTORY_PATH: &str = "databases";
|
||||
pub const DEFAULT_MAX_CONNECTIONS_PER_VAULT: u32 = 12;
|
||||
pub const DEFAULT_CURSOR_TIMEOUT: Duration = Duration::from_secs(60);
|
||||
pub const IDLE_POOL_TIMEOUT: Duration = Duration::from_secs(5 * 60);
|
||||
|
||||
pub const DEFAULT_HOST: &str = "127.0.0.1";
|
||||
pub const DEFAULT_PORT: u16 = 3000;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue