use std::collections::HashSet;
use std::path::{Path, PathBuf};
use async_trait::async_trait;
use tokio::sync::RwLock;
use crate::config::Settings;
use crate::watcher::{WatchAction, WatchError, WatchHandler};
pub struct ConfigFileHandler {
settings_path: PathBuf,
last_indexed_paths: RwLock<HashSet<PathBuf>>,
}
impl ConfigFileHandler {
pub fn new(settings_path: PathBuf) -> Result<Self, WatchError> {
let config = Settings::load_from(&settings_path).map_err(|e| WatchError::ConfigError {
reason: format!("Failed to load config: {e}"),
})?;
let initial_paths: HashSet<PathBuf> = config.indexing.indexed_paths.into_iter().collect();
Ok(Self {
settings_path,
last_indexed_paths: RwLock::new(initial_paths),
})
}
async fn compute_diff(&self) -> Result<(Vec<PathBuf>, Vec<PathBuf>), WatchError> {
let new_config =
Settings::load_from(&self.settings_path).map_err(|e| WatchError::ConfigError {
reason: format!("Failed to reload config: {e}"),
})?;
let new_paths: HashSet<PathBuf> = new_config.indexing.indexed_paths.into_iter().collect();
let last_paths = self.last_indexed_paths.read().await;
let added: Vec<PathBuf> = new_paths.difference(&last_paths).cloned().collect();
let removed: Vec<PathBuf> = last_paths.difference(&new_paths).cloned().collect();
if !added.is_empty() || !removed.is_empty() {
drop(last_paths);
let mut write_lock = self.last_indexed_paths.write().await;
*write_lock = new_paths;
}
Ok((added, removed))
}
}
#[async_trait]
impl WatchHandler for ConfigFileHandler {
fn name(&self) -> &str {
"config"
}
fn matches(&self, path: &Path) -> bool {
path == self.settings_path
}
async fn tracked_paths(&self) -> Vec<PathBuf> {
vec![self.settings_path.clone()]
}
async fn on_modify(&self, _path: &Path) -> Result<WatchAction, WatchError> {
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
let (added, removed) = self.compute_diff().await?;
if added.is_empty() && removed.is_empty() {
return Ok(WatchAction::None);
}
Ok(WatchAction::ReloadConfig { added, removed })
}
async fn on_delete(&self, _path: &Path) -> Result<WatchAction, WatchError> {
eprintln!(
"Warning: Config file {} was deleted",
self.settings_path.display()
);
Ok(WatchAction::None)
}
}