feat(watcher): watchers can now operate over entire workspaces, or individual projects
What does this MR do and why?
The primary change was the introduction of configurable watcher modes, which determines the granularity of reindexing operations. The modifications enable both workspace-level and project-level reindexing strategies.
Architectural Change: Configurable Watcher Granularity
The watcher system was modified to support two operational modes through a configuration-driven approach.
1. WatcherConfig Enhancement (crates/http-server/src/watcher.rs)
A new configuration system was implemented to control watcher behavior.
-
New Field: Added
single_watcher: booltoWatcherConfigstruct -
Builder Pattern: Implemented fluent configuration methods
periodic_force_index()andsingle_watcher() -
Default Behavior: Both flags default to
false, maintaining backward compatibility
2. Job Type Addition (crates/http-server/src/queue/job.rs)
A new job variant was added to support project-level reindexing.
-
New Job Variant:
ReindexProjectFolderWithWatchedFileswas added with fields:workspace_folder_path: Stringproject_folder_path: Stringproject_changes: Vec<PathBuf>priority: JobPriority
Implementation Details
3. Conditional Job Dispatch Logic (crates/http-server/src/watcher.rs)
The event processing logic was modified to dispatch different job types based on configuration.
-
Single Watcher Mode: When
single_watcheristrue, dispatchesReindexWorkspaceFolderWithWatchedFilesjobs -
Multiple Watcher Mode: When
single_watcherisfalse, dispatchesReindexProjectFolderWithWatchedFilesjobs -
Path Resolution: The
get_active_paths()function returns different path sets depending on the mode:- Single watcher: workspace folder paths only
- Multiple watcher: individual project paths within workspaces
4. Worker Implementation (crates/http-server/src/queue/worker.rs)
The worker was updated to handle the new job type.
-
Job Processing: Added
process_reindex_project_job()method to handle project-level reindexing -
Execution Strategy: Uses single-threaded execution (
threads = 1) to avoid performance issues - Error Handling: Implements comprehensive error handling for task execution, including panic recovery
5. Pathset Computation Logic
The compute_project_watcher_pathset() function was modified to handle both modes.
-
Condition Update: Changed from
if project_path != workspace_pathtoif project_path != workspace_path || watcher_config.single_watcher - Behavior: In single watcher mode, always uses recursive watching regardless of path equality
Related Issues
Testing
A test module was added to validate the configuration system.
- Configuration Tests: Validates default values and builder pattern functionality
- Integration Tests: Tests watcher creation with custom configurations
- Test Utilities: Helper functions for creating test workspace managers and job dispatchers
All existing tests pass.
Performance Analysis
Performance Checklist
-
Have you reviewed your memory allocations to ensure you're optimizing correctly? Are you cloning or copying unnecessary data? -
Have you profiled with cargo benchorcriterionto measure performance impact? -
Are you using zero-copy operations where possible (e.g., &strinstead ofString, slice references)? -
Have you considered using Cow<'_, T>for conditional ownership to avoid unnecessary clones? -
Are iterator chains and lazy evaluation being used effectively instead of intermediate collections? -
Are you reusing allocations where possible (e.g., Vec::clear()and reuse vs new allocation)? -
Have you considered using SmallVecor similar for small, stack-allocated collections? -
Are async operations properly structured to avoid blocking the executor? -
Have you reviewed unsafecode blocks for both safety and performance implications? -
Are you using appropriate data structures (e.g., HashMapvsBTreeMapvsIndexMap)? -
Have you considered compile-time optimizations (e.g., const fn, generics instead of trait objects)? -
Are debug assertions ( debug_assert!) used instead of runtime checks where appropriate?