Refactor notify dependency configuration and enhance VFS watch setup

- Updated Cargo.toml to conditionally configure the notify dependency for macOS and other platforms.
- Improved ServeSession's VFS watch logic to filter out ignored directories based on glob patterns, optimizing resource usage and watch handle count.
- Introduced PathIgnoreRule handling to streamline directory watching, enhancing overall performance and maintainability.
This commit is contained in:
Joe 2026-03-06 23:22:54 -06:00
parent 0243181731
commit 8acbfc0cf8
2 changed files with 40 additions and 9 deletions

View file

@ -21,8 +21,11 @@ log = "0.4"
notify-debouncer-full = "0.7" notify-debouncer-full = "0.7"
serde = { version = "1.0.228", features = ["derive"] } serde = { version = "1.0.228", features = ["derive"] }
[dependencies.notify] [target.'cfg(target_os = "macos")'.dependencies]
version = "8.2" notify = { version = "8.2", features = ["macos_kqueue"] }
[target.'cfg(not(target_os = "macos"))'.dependencies]
notify = "8.2"
[dev-dependencies] [dev-dependencies]
tempfile = "3.26.0" tempfile = "3.26.0"

View file

@ -17,7 +17,7 @@ use crate::{
session_id::SessionId, session_id::SessionId,
snapshot::{ snapshot::{
apply_patch_set, compute_patch_set, AppliedPatchSet, InstanceContext, InstanceSnapshot, apply_patch_set, compute_patch_set, AppliedPatchSet, InstanceContext, InstanceSnapshot,
PatchSet, RojoTree, PatchSet, PathIgnoreRule, RojoTree,
}, },
snapshot_middleware::{is_script_relevant_path, snapshot_from_vfs, INIT_FILE_PRIORITY}, snapshot_middleware::{is_script_relevant_path, snapshot_from_vfs, INIT_FILE_PRIORITY},
}; };
@ -371,21 +371,49 @@ impl ServeSession {
let patch_start = Instant::now(); let patch_start = Instant::now();
let project_folder = root_project.folder_location().to_path_buf(); let project_folder = root_project.folder_location().to_path_buf();
let watch_ignore_rules: Vec<PathIgnoreRule> = root_project
.glob_ignore_paths
.iter()
.map(|glob| PathIgnoreRule {
glob: glob.clone(),
base_path: root_project.folder_location().to_path_buf(),
})
.collect();
std::thread::scope(|s| { std::thread::scope(|s| {
s.spawn(|| { s.spawn(|| {
use walkdir::WalkDir;
let watch_start = Instant::now(); let watch_start = Instant::now();
// Watch each $path root recursively (NOT the project folder -- // Walk each $path root, skipping directories that match
// that would walk target/, .git/, etc. for repo-root projects). // globIgnorePaths, and watch each non-ignored directory
// individually (non-recursive). This avoids creating kqueue
// FDs for ignored subtrees on macOS.
let passes_ignore = |entry: &walkdir::DirEntry| -> bool {
watch_ignore_rules
.iter()
.all(|rule: &PathIgnoreRule| rule.passes(entry.path()))
};
vfs.set_watch_recursive(false);
let mut watch_count: usize = 0;
for root in &path_roots { for root in &path_roots {
let _ = vfs.watch(root); for entry in WalkDir::new(root)
.follow_links(true)
.into_iter()
.filter_entry(&passes_ignore)
.flatten()
{
if entry.file_type().is_dir() {
let _ = vfs.watch(entry.path());
watch_count += 1;
}
}
} }
// Watch project folder non-recursively for project file edits. // Watch project folder non-recursively for project file edits.
vfs.set_watch_recursive(false);
let _ = vfs.watch(&project_folder); let _ = vfs.watch(&project_folder);
vfs.set_watch_recursive(true); watch_count += 1;
log::debug!( log::debug!(
"Set up {} watches in {:.1?}", "Set up {} watches in {:.1?}",
path_roots.len() + 1, watch_count,
watch_start.elapsed(), watch_start.elapsed(),
); );
}); });