Implement comprehensive fixes for sync system issues

- Introduced a new plan to address eight identified issues in the sync system, including improvements to standalone script handling, property persistence, and file watcher behavior.
- Key changes include extracting standalone-to-directory conversion logic, enhancing property update persistence, and implementing a recovery mechanism for rapid delete+recreate scenarios.
- Added integration tests to ensure coverage for each fix and improve overall system reliability.
- Enhanced logging for VFS events to aid in debugging file watcher desynchronization issues.

This commit significantly improves the robustness of the sync system and addresses critical issues identified in the audit.
This commit is contained in:
Joe 2026-02-05 18:25:47 -06:00
parent 4a03d4bab5
commit 0968e74208
5 changed files with 1651 additions and 319 deletions

View file

@ -85,6 +85,11 @@ pub struct ServeSession {
/// A channel to send mutation requests on. These will be handled by the
/// ChangeProcessor and trigger changes in the tree.
tree_mutation_sender: Sender<PatchSet>,
/// Paths recently written by the API's syncback. The ChangeProcessor
/// checks this set and suppresses the file watcher echo for these paths
/// to avoid redundant re-snapshots and WebSocket messages.
suppressed_paths: Arc<Mutex<HashSet<std::path::PathBuf>>>,
}
impl ServeSession {
@ -132,6 +137,7 @@ impl ServeSession {
let vfs = Arc::new(vfs);
let (tree_mutation_sender, tree_mutation_receiver) = crossbeam_channel::unbounded();
let suppressed_paths = Arc::new(Mutex::new(HashSet::new()));
log::trace!("Starting ChangeProcessor");
let change_processor = ChangeProcessor::start(
@ -139,6 +145,7 @@ impl ServeSession {
Arc::clone(&vfs),
Arc::clone(&message_queue),
tree_mutation_receiver,
Arc::clone(&suppressed_paths),
);
Ok(Self {
@ -150,6 +157,7 @@ impl ServeSession {
message_queue,
tree_mutation_sender,
vfs,
suppressed_paths,
})
}
@ -165,6 +173,12 @@ impl ServeSession {
self.tree_mutation_sender.clone()
}
/// Returns a handle to the suppressed paths set, used to avoid
/// file watcher echo when the API writes files to disk.
pub fn suppressed_paths(&self) -> Arc<Mutex<HashSet<std::path::PathBuf>>> {
Arc::clone(&self.suppressed_paths)
}
#[allow(unused)]
pub fn vfs(&self) -> &Vfs {
&self.vfs