A Simple Debouncer For Rust's notify File Watcher

This is the initial Rust code I set up for my static site generator to rebuild the site when files change.

```cargo
[dependencies]
notify = "6.1.1"
notify-debouncer-full = "0.3.1"
```

use notify::{RecursiveMode, Watcher};
use notify_debouncer_full::new_debouncer;
use std::path::PathBuf;
use std::time::Duration;
use std::time::SystemTime;

pub fn main() {
    let path = PathBuf::from("/Users/alan/Desktop");
    let _ = watch_files(path);
}

fn watch_files(path: PathBuf) -> notify::Result<()> {
    let (tx, rx) = std::sync::mpsc::channel();
    let mut debouncer = new_debouncer(Duration::from_millis(500), None, tx)?;
    debouncer.watcher().watch(&path, RecursiveMode::Recursive)?;
    debouncer.cache().add_root(&path, RecursiveMode::Recursive);
    let mut last_update = SystemTime::now();
    let debounce_time = Duration::from_secs(4);
    for _result in rx {
        if last_update.elapsed().unwrap() > debounce_time {
            do_update();
            last_update = SystemTime::now();
        }
    }

    Ok(())
}

fn do_update() {
    dbg!("Change detected");
}
TODO: Show Results Output

Details

I shipped the first version of my static site generator. I've very happy with it and with being able to post again. Now that it builds it needs to build without me pressing buttons every time. To make that happen I'm using Rust's [TODO: Code shorthand span ] crate.

The notify create watches the file system and triggers when events happen. There's a debounce feature to help prevent spamming but it only works on individual files. So, if you have 1,400 files update on your website it would trigger 1,400 builds.

Oops.

I added a simple debouncer on top on the one that comes with notify to prevent that. It checks a time stamp to see if more than 4 seconds have passed since that last build when a file change is detected. If that's the case, it sends the signal to build and updates the time stamp. Otherwise it does nothing.

I spent half a day trying to build a more sophisticated method. Then it clicked that I really don't need anything more that this.

Notes

Keep these for writing up the larger one that wathces specifci files

// https://doc.rust-lang.org/std/time/struct.SystemTime.html // https://docs.rs/notify/latest/notify/event/enum.EventKind.html // https://docs.rs/notify/latest/notify/event/enum.ModifyKind.html

Note

See also: Watch A Directory For File Changes In Rust which uses _mini instead of _full. I'm probably not going to use it that much since any access to a file with _mini triggers an event and genearlly that's not what I want. I usually after create or update and sometimes delete

~ fin ~

References

  • This is the page where I got most of the code