yamlbase 0.7.2

A lightweight SQL server that serves YAML-defined tables over standard SQL protocols
Documentation
use notify::RecursiveMode;
use notify_debouncer_mini::new_debouncer;
use std::path::PathBuf;
use std::time::Duration;
use tokio::sync::mpsc;
use tracing::{error, info};

pub struct FileWatcher {
    path: PathBuf,
    tx: mpsc::Sender<()>,
}

impl FileWatcher {
    pub fn new(path: PathBuf) -> (Self, mpsc::Receiver<()>) {
        let (tx, rx) = mpsc::channel(10);

        let watcher = Self { path, tx };
        (watcher, rx)
    }

    pub fn start(self) -> anyhow::Result<()> {
        let path = self.path.clone();
        let tx = self.tx.clone();

        std::thread::spawn(move || {
            if let Err(e) = watch_file(path, tx) {
                error!("File watcher error: {}", e);
            }
        });

        Ok(())
    }
}

fn watch_file(path: PathBuf, tx: mpsc::Sender<()>) -> anyhow::Result<()> {
    let (tx_debounced, rx_debounced) = std::sync::mpsc::channel();

    let mut debouncer = new_debouncer(Duration::from_secs(1), tx_debounced)?;

    debouncer
        .watcher()
        .watch(&path, RecursiveMode::NonRecursive)?;

    info!("Watching for changes to: {}", path.display());

    for event in rx_debounced {
        match event {
            Ok(events) => {
                for e in events {
                    if e.path == path {
                        info!("File changed, triggering reload");
                        let tx = tx.clone();
                        tokio::spawn(async move {
                            let _ = tx.send(()).await;
                        });
                    }
                }
            }
            Err(e) => error!("Watch error: {:?}", e),
        }
    }

    Ok(())
}