Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include watched path in Event when watching multiple paths recursively #609

Open
Javex opened this issue Jun 27, 2024 · 1 comment
Open

Comments

@Javex
Copy link

Javex commented Jun 27, 2024

When watching multiple directories recursively, I would like to know which base path an event belongs to. For example with this setup:

pub fn watch(watches: Vec<&Path>, tx: Sender<MetricMessage>) -> Result<RecommendedWatcher> {
    let watches_matcher: Vec<PathBuf> = watches.iter().map(|p| PathBuf::from(p)).collect();
    let mut watcher = notify::recommended_watcher(move |res: notify::Result<notify::Event>| {
        handle_notify_event(&watches_matcher, &tx, res)
    })?;
    for watch in watches {
        watcher.watch(watch, RecursiveMode::Recursive)?;
    }

    Ok(watcher)
}

If I supply multiple paths and then handle the resulting events, I don't know which watch those were for. In my use case, I want to count events by base path to measure how busy they are.

Right now I do this:

    for base in base_paths {
        for event_path in paths.iter() {
            if event_path.starts_with(base) {
                return Ok(base.to_string_lossy().to_string());
            }
        }
    }

If there is a lot of events and many monitored paths this could get quite expensive. I noticed that inotify returns a WatchDescriptor which is contained in an Event. A similar approach would be great here, where the watcher returns some form of handle or descriptor that can be attached to each event.

This would have to be a separate descriptor that tracks which recursively created watches belong to which "root watch" as the event.wd descriptor used at https://github.com/notify-rs/notify/blob/main/notify/src/inotify.rs#L216 is some leaf node. So in the recursive case the original path would have to be tracked here where the information is currently "lost".

I think another wrinkle is the fact that the closure has to be specified upon calling INotifyWatcher::new which would make it difficult to pass any subsequent descriptors created by watcher.watch back to that closure. It would be great to have a separate allocation e.g. via builder pattern where I specify all my watches first, get handles back and then pass in the closure which can track those handles. Of course, this could all abstracted away by passing through the root path as part of the event rather than dealing with generic descriptors.

Is this something worth implementing?

@0xpr03
Copy link
Member

0xpr03 commented Jun 28, 2024

Please note that you have to make an equal proposal for handling this on all other backends (fsevent,kqueue,windows,pollwatcher) before this could proceed to a MR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants