diff --git a/sync-server/src/app_state/database.rs b/sync-server/src/app_state/database.rs index 9aa99db5..29118240 100644 --- a/sync-server/src/app_state/database.rs +++ b/sync-server/src/app_state/database.rs @@ -2,7 +2,7 @@ use core::time::Duration; use std::{ collections::HashMap, path::{Path, PathBuf}, - sync::Arc, + sync::{Arc, Weak}, }; use anyhow::{Context as _, Result}; @@ -48,6 +48,7 @@ impl std::fmt::Debug for PoolWithTimestamp { pub struct Database { config: DatabaseConfig, connection_pools: Arc>>, + opening_pools: Arc>>>>, } pub type Transaction<'a> = sqlx::Transaction<'a, Sqlite>; @@ -66,25 +67,13 @@ impl Database { ) })?; - info!("Applying pending database migrations"); - - // Filenames encode only a digest, so their vault names cannot be - // recovered here. Check migrations now and open pools lazily by name. - let mut entries = tokio::fs::read_dir(&vault_directory).await?; - while let Some(entry) = entries.next_entry().await? { - if entry.file_type().await?.is_file() - && entry.path().extension().is_some_and(|ext| ext == "sqlite") - { - Self::open_database(config, &entry.path()) - .await? - .close() - .await; - } - } + // SQLite flushes its own files, not ancestors created by this process + Self::flush_directory_ancestors(&vault_directory).await?; let database = Self { config: config.clone(), connection_pools: Arc::default(), + opening_pools: Arc::default(), }; // Start background task to cleanup idle connection pools @@ -127,9 +116,27 @@ impl Database { Self::run_migrations(&pool).await?; + if let Some(directory) = file_name.parent() { + #[cfg(unix)] + Self::flush_directory_ancestors(directory).await?; + } + Ok(pool) } + async fn flush_directory_ancestors(directory: &Path) -> Result<()> { + let directory = tokio::fs::canonicalize(directory).await?; + for ancestor in directory.ancestors() { + tokio::fs::File::open(ancestor) + .await? + .sync_all() + .await + .with_context(|| format!("Cannot flush directory {}", ancestor.display()))?; + } + + Ok(()) + } + async fn run_migrations(pool: &Pool) -> Result<()> { sqlx::migrate!("src/app_state/database/migrations") .run(pool)