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
3 changes: 3 additions & 0 deletions changelog.d/23820_watch_config_handle_events.fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The configuration watcher now collects event paths even during the delay period. These were previously ignored and prevented components from reloading.

authors: nekorro
5 changes: 4 additions & 1 deletion src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ impl ComponentConfig {
}
}

pub fn contains(&self, config_paths: &[PathBuf]) -> Option<(ComponentKey, ComponentType)> {
pub fn contains(
&self,
config_paths: &HashSet<PathBuf>,
) -> Option<(ComponentKey, ComponentType)> {
if config_paths.iter().any(|p| self.config_paths.contains(p)) {
return Some((self.component_key.clone(), self.component_type.clone()));
}
Expand Down
33 changes: 25 additions & 8 deletions src/config/watcher.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use notify::{EventKind, RecursiveMode, recommended_watcher};
use std::{
collections::HashMap,
collections::{HashMap, HashSet},
path::{Path, PathBuf},
sync::mpsc::{Receiver, channel},
thread,
time::Duration,
};

use notify::{EventKind, RecursiveMode, recommended_watcher};

use crate::{
Error,
config::{ComponentConfig, ComponentType},
Expand Down Expand Up @@ -42,7 +41,11 @@ enum Watcher {
impl Watcher {
fn add_paths(&mut self, config_paths: &[PathBuf]) -> Result<(), Error> {
for path in config_paths {
self.watch(path, RecursiveMode::Recursive)?;
if path.exists() {
self.watch(path, RecursiveMode::Recursive)?;
} else {
debug!(message = "Skipping non-existent path.", path = ?path);
}
}
Ok(())
}
Expand Down Expand Up @@ -99,15 +102,29 @@ pub fn spawn_thread<'a>(
) {
debug!(message = "Configuration file change detected.", event = ?event);

// Consume events until delay amount of time has passed since the latest event.
while receiver.recv_timeout(delay).is_ok() {}
// Collect paths from initial event
let mut changed_paths: HashSet<PathBuf> = event.paths.into_iter().collect();

// Collect paths from subsequent events until delay amount of time has passed
while let Ok(Ok(subseq_event)) = receiver.recv_timeout(delay) {
if matches!(
subseq_event.kind,
EventKind::Create(_) | EventKind::Remove(_) | EventKind::Modify(_)
) {
changed_paths.extend(subseq_event.paths);
}
}

debug!(message = "Consumed file change events for delay.", delay = ?delay);
debug!(
message = "Collected file change events during delay period.",
paths = changed_paths.len(),
delay = ?delay
);

let changed_components: HashMap<_, _> = component_configs
.clone()
.into_iter()
.flat_map(|p| p.contains(&event.paths))
.flat_map(|p| p.contains(&changed_paths))
.collect();

// We need to read paths to resolve any inode changes that may have happened.
Expand Down
Loading