From adc8d4e1e70b9e252caa0bc6ba729fa3c0ef4dbd Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Tue, 30 Jul 2024 19:18:43 +0200 Subject: [PATCH] File watch events: Add dynamic wait period before writing new changes (#12585) --- Cargo.lock | 1 + crates/red_knot/Cargo.toml | 1 + crates/red_knot/tests/file_watching.rs | 23 ++++++++++++++++++----- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc612cfa77..e4b3156f04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1944,6 +1944,7 @@ dependencies = [ "countme", "crossbeam", "ctrlc", + "filetime", "notify", "rayon", "red_knot_module_resolver", diff --git a/crates/red_knot/Cargo.toml b/crates/red_knot/Cargo.toml index a4c6166d60..5434852061 100644 --- a/crates/red_knot/Cargo.toml +++ b/crates/red_knot/Cargo.toml @@ -27,6 +27,7 @@ notify = { workspace = true } rayon = { workspace = true } rustc-hash = { workspace = true } salsa = { workspace = true } +filetime = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } tracing-tree = { workspace = true } diff --git a/crates/red_knot/tests/file_watching.rs b/crates/red_knot/tests/file_watching.rs index 3f3db3b6e5..1396c56c2b 100644 --- a/crates/red_knot/tests/file_watching.rs +++ b/crates/red_knot/tests/file_watching.rs @@ -3,6 +3,7 @@ use std::time::Duration; use anyhow::{anyhow, Context}; +use filetime::FileTime; use salsa::Setter; use red_knot::db::RootDatabase; @@ -184,12 +185,24 @@ where } /// The precision of the last modified time is platform dependent and not arbitrarily precise. -/// This method sets the current thread to sleep for a duration that -/// is larger than the [last-modified precision on all platforms](https://doc.rust-lang.org/nightly/std/time/struct.SystemTime.html#platform-specific-behavior). -/// -/// Calling the function is only necessary when making changes to an **existing** file. +/// This method sleeps until the last modified time of a newly created file changes. This guarantees +/// that the last modified time of any file written **after** this method completes should be different. fn next_io_tick() { - std::thread::sleep(Duration::from_nanos(200)); + let temp = tempfile::tempfile().unwrap(); + + let last_modified = FileTime::from_last_modification_time(&temp.metadata().unwrap()); + + loop { + filetime::set_file_handle_times(&temp, None, Some(FileTime::now())).unwrap(); + + let new_last_modified = FileTime::from_last_modification_time(&temp.metadata().unwrap()); + + if new_last_modified != last_modified { + break; + } + + std::thread::sleep(Duration::from_nanos(100)); + } } #[test]