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"
serde = { version = "1.0.228", features = ["derive"] }
[dependencies.notify]
version = "8.2"
[target.'cfg(target_os = "macos")'.dependencies]
notify = { version = "8.2", features = ["macos_kqueue"] }
[target.'cfg(not(target_os = "macos"))'.dependencies]
notify = "8.2"
[dev-dependencies]
tempfile = "3.26.0"

View file

@ -17,7 +17,7 @@ use crate::{
session_id::SessionId,
snapshot::{
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},
};
@ -371,21 +371,49 @@ impl ServeSession {
let patch_start = Instant::now();
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| {
s.spawn(|| {
use walkdir::WalkDir;
let watch_start = Instant::now();
// Watch each $path root recursively (NOT the project folder --
// that would walk target/, .git/, etc. for repo-root projects).
// Walk each $path root, skipping directories that match
// 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 {
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.
vfs.set_watch_recursive(false);
let _ = vfs.watch(&project_folder);
vfs.set_watch_recursive(true);
watch_count += 1;
log::debug!(
"Set up {} watches in {:.1?}",
path_roots.len() + 1,
watch_count,
watch_start.elapsed(),
);
});