Skip to main content

Crate extended_notify

Crate extended_notify 

Source
Expand description

Extended filesystem watcher built on notify.

This crate extends notify with several features:

  • Watch non-existent paths: When you watch a path that doesn’t exist, the nearest existing ancestor is watched instead, and polling detects when the target path comes into existence. This is useful for watching config files that may be created later, or paths on removable media.

  • Interest-based filtering: Rather than receiving all events and filtering yourself, specify exactly which event types matter to you. Interests are hierarchical—subscribing to Interest::Delete receives all deletion events, while Interest::DeleteFile only receives file deletions.

  • RAII watch handles: The Watched handle returned by Watcher::add automatically stops the watch when dropped. No manual cleanup required.

  • Synthetic events: When a non-existent path comes into existence (or vice versa), synthetic Interest::Create and Interest::Delete events are generated if you’ve subscribed to them.

  • Establishment notification: Subscribe to Interest::Established to receive a synthetic event when the watch is first set up, useful for triggering an initial read of the watched path.

  • Multiple Watches: Multiple watches for the same file or directory are handled gracefully. Both watches will behave correctly, but only one Notify watch will be created.

§Example

use extended_notify::{ArcPath, EventBatch, EventHandler, Interest, WatcherConfigBuilder};
use anyhow::Result;
use enumflags2::make_bitflags;

#[derive(Clone)]
struct MyHandler;

impl EventHandler for MyHandler {
    async fn handle_event(&mut self, batch: EventBatch) -> Result<()> {
        for (id, event) in batch.iter() {
            println!("{:?}: {:?}", id, event);
        }
        Ok(())
    }
}

let watcher = WatcherConfigBuilder::default()
    .event_handler(MyHandler)
    .build()?
    .start()?;

// Watch a path that may or may not exist yet
let interest = make_bitflags!(Interest::{Create | Delete | Modify});
let handle = watcher.add(ArcPath::from("/tmp/my-config"), interest)?;

// Events flow to MyHandler::handle_event
// Watch stops when handle is dropped

§Event Delivery

Events are delivered in batches through the EventHandler trait. Each batch contains (Id, Event) pairs, where the Id identifies which watch generated the event. Multiple events for the same watch may be coalesced into a single Event with multiple paths.

If your handler returns an error, the watcher task stops and all subsequent operations on the Watcher will fail.

§Polling

Polling runs alongside native filesystem notifications to handle cases notifications can’t cover—primarily detecting when non-existent paths come into existence. By default, 100 paths are checked each second. Adjust with Watcher::set_poll_interval and Watcher::set_poll_batch, or disable polling entirely by setting the batch size to 0.

If you disable polling creation of a file and multiple levels of directories may not be detected. For example if you watch a file /foo/bar/baz that does not exist, and you disable polling, if only /foo exists to start, and /foo/bar is created, then /foo/bar/baz is created, you may not get the create event for /foo/bar/baz.

Structs§

ArcPath
Event
Id
Watched
A watched path
Watcher
An filesystem watcher
WatcherConfig
WatcherConfigBuilder
Builder for WatcherConfig.

Enums§

EventKind
Interest
WatcherConfigBuilderError
Error type for WatcherConfigBuilder

Constants§

MIN_POLL_INTERVAL

Traits§

EventHandler

Type Aliases§

EventBatch
A batch of events delivered to the EventHandler.