Add EventKindMask for filtering filesystem events#736
Add EventKindMask for filtering filesystem events#736JohnTitor merged 11 commits intonotify-rs:mainfrom
Conversation
|
Would really love this feature to be merged. Should this be on the |
I went with Config because it better fit my use case. I wasn't trying to have a mix of event levels. I think if we want different event levels we could start a few watchers? |
| let mut watch_mask = WatchMask::empty(); | ||
|
|
||
| if mask.intersects(EventKindMask::CREATE) { | ||
| watch_mask |= WatchMask::CREATE | WatchMask::MOVED_TO; |
There was a problem hiding this comment.
I think it maybe rally confusing, if user requested recursive watch with ignored create events. In that case subdirectories created after a watch call will not be watched
There was a problem hiding this comment.
Got it.
Recursive watches now always register for CREATE/MOVED_TO at the kernel level, then filter in userspace before delivery. This ensures subdirectory tracking works regardless of the user's EventKindMask.
| impl ReadDirectoryChangesWatcher { | ||
| pub fn create( | ||
| event_handler: Arc<Mutex<dyn EventHandler>>, | ||
| event_kinds: EventKindMask, |
There was a problem hiding this comment.
Note: this is a technically breaking change. It doesn't mean we should change it but it would require a major release.
JohnTitor
left a comment
There was a problem hiding this comment.
Needs to resolve the conflict but otherwise LGTM
| follow_links: bool, | ||
| config: &Config, |
- Change EventKindMask::default() from CORE to ALL to match Config::default().event_kinds() - Add userspace event filtering to PollWatcher via EventEmitter - Filter events in emit_ok() using EventKindMask::matches() - Error events always pass through (not filtered) - Add test verifying CREATE-only mask filters MODIFY events - Add cross-crate consistency test for defaults This is part of the EventKindMask cross-platform filtering feature. PollWatcher now respects the event_kinds config, filtering events before delivery to the user's handler.
Adds userspace event filtering to the kqueue backend by storing the EventKindMask from Config and checking events against it before delivering to the handler. This follows the same pattern established in PollWatcher. - Store event_kinds in EventLoop struct - Pass event_kinds from Config through the constructor chain - Filter OK events before calling handle_event(), errors pass through - Add test for filtering behavior (requires BSD/macOS to run)
Add event filtering to the FSEvents (macOS) backend by calling EventKindMask::matches() before delivering events to the handler. This follows the same pattern established in kqueue and PollWatcher. Changes: - Add event_kinds field to FsEventWatcher and StreamContextInfo - Pass event_kinds from Config through to the callback context - Filter events in callback_impl based on the mask - Add test for filtering behavior
Thread EventKindMask through ReadDirectoryChangesServer and start_read to filter events before delivery. Events that don't match the mask are silently dropped, while errors always pass through.
Change test infrastructure ChannelConfig::default() to use Config::default() which includes EventKindMask::ALL instead of CORE. This ensures tests cover all event types including Access events. Updated inotify tests to use wait_ordered() instead of wait_ordered_exact() where appropriate, since with ALL events we may get directory access events that are timing-dependent. Tests that check for absence of specific events now filter out Access events to focus on the behavior being tested.
kqueue uses userspace filtering via EventKindMask::matches(), only inotify has kernel-level support via WatchMask translation. Updated documentation in: - notify-types/src/event.rs: EventKindMask doc comment - notify/src/config.rs: with_event_kinds() doc comment
Use blocking recv_timeout instead of try_iter to avoid race condition between poll thread processing the message and test collecting events.
Recursive watches now always register for CREATE/MOVED_TO at the kernel level, then filter in userspace before delivery. This ensures subdirectory tracking works regardless of the user's EventKindMask.
a706125 to
133cc3b
Compare
|
Sorry, I'm used to my git hooks enforcing that one but I don't have any setup on this repo. I fixed it. |
| const ALL_ACCESS = Self::ACCESS_OPEN.bits() | Self::ACCESS_CLOSE.bits() | Self::ACCESS_CLOSE_NOWRITE.bits(); | ||
|
|
||
| /// Core events: create, remove, and all modify events. | ||
| /// This is the default and matches the current notify behavior (no access events). |
There was a problem hiding this comment.
This is the default
Fairly sure that’s an error, EventKindMask::default() returns ALL and Config::default() uses ALL.
I also don’t know what “current notify behavior” means in this context. But I don’t imagine most users want access events.
There was a problem hiding this comment.
Good catch, fixed in #819.
But I don’t imagine most users want access events.
Yeah, likely. But I'd like to change it carefully as it's behavior change. Maybe we can consider changing if someone files a request (and receives positive reactions).
Adds EventKindMask, a bitflags-based type that allows users to configure which event kinds they want to receive. This is configured via Config::with_event_kinds().
This feature allows filtering at the source. On Linux (inotify), filtering happens at the kernel level via WatchMask translation, so unwanted events never reach userspace. On other backends, filtering is applied early in the event pipeline.
Existing users shouldn't see any breaking changes. The default (EventKindMask::ALL) should preserve existing behavior.
Usage
Changes