Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 20 additions & 6 deletions examples/debouncer_full.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use std::{fs, thread, time::Duration};

use notify::RecursiveMode;
use notify_debouncer_full::new_debouncer;
use notify::{EventKindMask, RecommendedWatcher, RecursiveMode};
use notify_debouncer_full::{new_debouncer_opt, notify, RecommendedCache};
use tempfile::tempdir;

/// Advanced example of the notify-debouncer-full, accessing the internal file ID cache
/// Advanced example of the notify-debouncer-full with event filtering.
///
/// This demonstrates using new_debouncer_opt() to pass a custom notify::Config
/// that filters events at the kernel level (on Linux), reducing noise and
/// improving performance.
fn main() -> Result<(), Box<dyn std::error::Error>> {
let dir = tempdir()?;
let dir_path = dir.path().to_path_buf();
Expand All @@ -25,11 +29,21 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}
});

// setup debouncer
// setup debouncer with custom event filtering
let (tx, rx) = std::sync::mpsc::channel();

// no specific tickrate, max debounce time 2 seconds
let mut debouncer = new_debouncer(Duration::from_secs(2), None, tx)?;
// Configure notify to exclude noisy access events (OPEN/CLOSE)
// Use CORE mask: CREATE, REMOVE, MODIFY_DATA, MODIFY_META, MODIFY_NAME
let notify_config = notify::Config::default().with_event_kinds(EventKindMask::CORE);

// Use new_debouncer_opt for full control over the watcher configuration
let mut debouncer = new_debouncer_opt::<_, RecommendedWatcher, RecommendedCache>(
Duration::from_secs(2), // debounce timeout
None, // tick rate (None = auto)
tx,
RecommendedCache::new(),
notify_config,
)?;

debouncer.watch(dir.path(), RecursiveMode::Recursive)?;

Expand Down
20 changes: 14 additions & 6 deletions examples/debouncer_mini.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use std::{path::Path, time::Duration};

use notify::RecursiveMode;
use notify_debouncer_mini::new_debouncer;
use notify::{EventKindMask, RecommendedWatcher, RecursiveMode};
use notify_debouncer_mini::{new_debouncer_opt, Config};

/// Example for debouncer mini
/// Example for debouncer mini with event filtering.
///
/// This demonstrates using Config::with_notify_config() to pass a custom notify::Config
/// that filters events at the kernel level (on Linux), reducing noise.
fn main() {
env_logger::Builder::from_env(
env_logger::Env::default().default_filter_or("debouncer_mini=trace"),
Expand All @@ -29,11 +32,16 @@ fn main() {
}
});

// setup debouncer
// setup debouncer with custom event filtering
let (tx, rx) = std::sync::mpsc::channel();

// No specific tickrate, max debounce time 1 seconds
let mut debouncer = new_debouncer(Duration::from_secs(1), tx).unwrap();
// Configure debouncer with notify config that excludes access events
// CORE mask: CREATE, REMOVE, MODIFY_DATA, MODIFY_META, MODIFY_NAME
let config = Config::default()
.with_timeout(Duration::from_secs(1))
.with_notify_config(notify::Config::default().with_event_kinds(EventKindMask::CORE));

let mut debouncer = new_debouncer_opt::<_, RecommendedWatcher>(config, tx).unwrap();

debouncer
.watcher()
Expand Down
105 changes: 105 additions & 0 deletions examples/event_filtering.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/// Example demonstrating EventKindMask for filtering filesystem events.
///
/// EventKindMask allows you to configure which types of events you want to receive,
/// reducing noise and improving performance by filtering at the kernel level (on Linux).
///
/// Run with: cargo run --example event_filtering -- <path>
use notify::{Config, EventKindMask, RecommendedWatcher, RecursiveMode, Watcher};
use std::path::Path;

fn main() {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();

let path = std::env::args()
.nth(1)
.expect("Argument 1 needs to be a path");

log::info!("Watching {path}");

// Choose which event filtering mode to demonstrate
let mode = std::env::args().nth(2).unwrap_or_default();
let result = match mode.as_str() {
"core" => {
log::info!("Mode: CORE (excludes access events like OPEN/CLOSE)");
watch_core(&path)
}
"create-remove" => {
log::info!("Mode: CREATE | REMOVE only");
watch_create_remove(&path)
}
_ => {
log::info!("Mode: ALL (default, receives all events)");
log::info!(" Use 'core' or 'create-remove' as 2nd arg for other modes");
watch_all(&path)
}
};

if let Err(error) = result {
log::error!("Error: {error:?}");
}
}

/// Watch with ALL events (default behavior, backward compatible)
fn watch_all<P: AsRef<Path>>(path: P) -> notify::Result<()> {
let (tx, rx) = std::sync::mpsc::channel();

// Default config receives all events including access events (OPEN, CLOSE)
let config = Config::default();
// Equivalent to: Config::default().with_event_kinds(EventKindMask::ALL)

let mut watcher = RecommendedWatcher::new(tx, config)?;
watcher.watch(path.as_ref(), RecursiveMode::Recursive)?;

for res in rx {
match res {
Ok(event) => log::info!("Event: {event:?}"),
Err(error) => log::error!("Error: {error:?}"),
}
}

Ok(())
}

/// Watch with CORE events only (excludes noisy access events)
///
/// CORE includes: CREATE, REMOVE, MODIFY_DATA, MODIFY_META, MODIFY_NAME
/// Excludes: ACCESS_OPEN, ACCESS_CLOSE, ACCESS_CLOSE_NOWRITE
fn watch_core<P: AsRef<Path>>(path: P) -> notify::Result<()> {
let (tx, rx) = std::sync::mpsc::channel();

// CORE mask excludes access events, reducing noise significantly
let config = Config::default().with_event_kinds(EventKindMask::CORE);

let mut watcher = RecommendedWatcher::new(tx, config)?;
watcher.watch(path.as_ref(), RecursiveMode::Recursive)?;

for res in rx {
match res {
Ok(event) => log::info!("Event: {event:?}"),
Err(error) => log::error!("Error: {error:?}"),
}
}

Ok(())
}

/// Watch only file creation and removal events
fn watch_create_remove<P: AsRef<Path>>(path: P) -> notify::Result<()> {
let (tx, rx) = std::sync::mpsc::channel();

// Custom mask: only CREATE and REMOVE events
let config =
Config::default().with_event_kinds(EventKindMask::CREATE | EventKindMask::REMOVE);

let mut watcher = RecommendedWatcher::new(tx, config)?;
watcher.watch(path.as_ref(), RecursiveMode::Recursive)?;

for res in rx {
match res {
Ok(event) => log::info!("Event: {event:?}"),
Err(error) => log::error!("Error: {error:?}"),
}
}

Ok(())
}
2 changes: 2 additions & 0 deletions notify-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ repository.workspace = true

[features]
serialization-compat-6 = []
serde = ["dep:serde", "bitflags/serde"]

[dependencies]
bitflags = "2"
serde = { workspace = true, optional = true }
web-time = { workspace = true, optional = true }

Expand Down
Loading