Skip to content

Commit

Permalink
feat(watcher): Use notify_debouncer_full
Browse files Browse the repository at this point in the history
Based on code by @nyarly, this debounces watch events before filtering
file paths.

`notify_debouncer_full` will do the hard part of making sure spurious
events are sufficiently removed before we match on them. From the
docs:

* Only emits a single Rename event if the rename From and To events can be matched
* Merges multiple Rename events
* Takes Rename events into account and updates paths for events that occurred before the rename event, but which haven't been emitted, yet
* Optionally keeps track of the file system IDs all files and stiches rename events together (FSevents, Windows)
* Emits only one Remove event when deleting a directory (inotify)
* Doesn't emit duplicate create events
* Doesn't emit Modify events after a Create event
  • Loading branch information
Profpatsch committed Apr 30, 2024
1 parent 7442674 commit faa2736
Show file tree
Hide file tree
Showing 4 changed files with 325 additions and 140 deletions.
80 changes: 79 additions & 1 deletion Cargo.lock

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

7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ thiserror = "1.0"

# TODO: update to 0.3
structopt.version = "0.2"

# TODO: update to 0.3
structopt.default-features = false

# TODO: update to 0.3
structopt.features = [
# "default",
"suggestions",
Expand Down Expand Up @@ -55,11 +59,14 @@ lazy_static = "1.4.0"
md5 = "0.7.0"
vec1 = ">= 1.1.0, <1.7.0"
human-panic = { path = "vendor/human-panic" }
notify-debouncer-full = "0.3.1"

[dev-dependencies]
# 1.0.0 requires at least rust 1.50
proptest.version = "0.10.1"
# 1.0.0 requires at least rust 1.50
proptest.default-features = false
# 1.0.0 requires at least rust 1.50
proptest.features = [
"std",
# reenable if proptest kills the test runner
Expand Down
32 changes: 15 additions & 17 deletions src/build_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,10 @@ impl<'a> BuildLoop<'a> {
nix_gc_root_user_dir: project::NixGcRootUserDir,
logger: slog::Logger,
) -> anyhow::Result<BuildLoop<'a>> {
let mut watch = Watch::new(logger.clone()).map_err(|err| anyhow!(err))?;
let watch = Watch::new(&logger).map_err(|err| anyhow!(err))?;
watch
.extend(vec![WatchPathBuf::Normal(
.add_to_watch_tx
.send(vec![WatchPathBuf::Normal(
project.nix_file.as_absolute_path().to_owned(),
)])
.with_context(|| {
Expand Down Expand Up @@ -201,7 +202,7 @@ impl<'a> BuildLoop<'a> {
rx_ping: chan::Receiver<()>,
) -> crate::Never {
let mut current_build = BuildState::NotRunning;
let rx_watcher = self.watch.rx.clone();
let rx_watcher = self.watch.watch_events_rx.clone();

loop {
debug!(self.logger, "looping build_loop";
Expand Down Expand Up @@ -247,19 +248,13 @@ impl<'a> BuildLoop<'a> {

// watcher found file change
recv(rx_watcher) -> msg => match msg {
Ok(msg) => {
match self.watch.process_watch_events(msg) {
Some(changed) => {
// TODO: this is not a started, this is just a scheduled!
send_event(Event::Started {
nix_file: self.project.nix_file.clone(),
reason: Reason::FilesChanged(changed)
});
self.start_or_schedule_build(&mut current_build)
},
// No relevant file events
None => {}
}
Ok(changed) => {
// TODO: this is not a started, this is just a scheduled!
send_event(Event::Started {
nix_file: self.project.nix_file.clone(),
reason: Reason::FilesChanged(changed)
});
self.start_or_schedule_build(&mut current_build)
},
Err(chan::RecvError) =>
debug!(self.logger, "notify chan was disconnected"; "project" => &self.project.nix_file)
Expand Down Expand Up @@ -340,7 +335,10 @@ impl<'a> BuildLoop<'a> {
debug!(self.logger, "paths reduced"; "from" => original_paths_len, "to" => paths.len());

// add all new (reduced) nix sources to the input source watchlist
self.watch.extend(paths.into_iter().collect::<Vec<_>>())?;
self.watch
.add_to_watch_tx
.send(paths.into_iter().collect::<Vec<_>>())
.map_err(BuildError::io)?;

// root the result
self.project
Expand Down
Loading

0 comments on commit faa2736

Please sign in to comment.