diff --git a/crates/pdfs-fuse/src/sim/daemon.rs b/crates/pdfs-fuse/src/sim/daemon.rs index c8a33a1..fb9bce2 100644 --- a/crates/pdfs-fuse/src/sim/daemon.rs +++ b/crates/pdfs-fuse/src/sim/daemon.rs @@ -465,4 +465,49 @@ mod tests { assert!(matches!(daemon.stop(), Ok(MountOutcome::Shutdown))); let _ = std::fs::remove_dir_all(&dir); } + + /// Make 100 folders of 10 empty files each through a mount on `faults`, and + /// time the syscalls and then the drain until Drive holds all of it. + fn time_a_thousand_files(faults: Faults) -> (Duration, Duration) { + let drive = FakeDrive::new(); + let dir = scratch("thousand"); + let daemon = Daemon::start(&dir, drive.client(1, faults)).unwrap(); + let start = Instant::now(); + for folder in 0..100 { + let folder = daemon.mountpoint.join(format!("d{folder:03}")); + std::fs::create_dir(&folder).unwrap(); + for file in 0..10 { + std::fs::File::create(folder.join(format!("f{file}"))).unwrap(); + } + } + let syscalls = start.elapsed(); + let start = Instant::now(); + assert!( + wait_until(Duration::from_secs(1800), || { + drive.tree().len() == 1100 && daemon.pending().is_ok_and(|ops| ops.is_empty()) + }), + "the drain did not finish: {} of 1100 on Drive", + drive.tree().len() + ); + let drain = start.elapsed(); + assert!(matches!(daemon.stop(), Ok(MountOutcome::Shutdown))); + let _ = std::fs::remove_dir_all(&dir); + (syscalls, drain) + } + + /// The milestone's speed target: a thousand files reach Drive as fast on + /// Wi-Fi as on a LAN. It only measures for now, and takes minutes, so it + /// runs when `PDFS_SIM_MEASURE` is set. + #[test] + #[ignore = "mounts FUSE: run with `PDFS_SIM_MEASURE=1 cargo test -p pdfs-fuse sim:: -- --ignored`"] + fn a_thousand_files_drain_as_fast_on_wifi_as_on_lan() { + if std::env::var_os("PDFS_SIM_MEASURE").is_none() { + eprintln!("skipped: set PDFS_SIM_MEASURE to measure the drain"); + return; + } + let (lan_syscalls, lan_drain) = time_a_thousand_files(Faults::lan()); + let (wifi_syscalls, wifi_drain) = time_a_thousand_files(Faults::wifi()); + eprintln!("lan: syscalls {lan_syscalls:?}, drain {lan_drain:?}"); + eprintln!("wifi: syscalls {wifi_syscalls:?}, drain {wifi_drain:?}"); + } } diff --git a/crates/pdfs-fuse/src/sim/run.rs b/crates/pdfs-fuse/src/sim/run.rs index a94d705..7f901b8 100644 --- a/crates/pdfs-fuse/src/sim/run.rs +++ b/crates/pdfs-fuse/src/sim/run.rs @@ -1044,6 +1044,21 @@ mod tests { drain_budget: Duration::from_secs(120), }; + /// Wi-Fi's latency, lag and lost replies without the outages: the queue + /// has to drain within a settle, not merely by the end. + static ONE_CLIENT_WIFI: Profile = Profile { + name: "one-client-wifi", + clients: 1, + steps: 80, + faults: Faults::wifi, + link_flaps: false, + restarts: false, + deletes_mid_upload: false, + settle_budget: Some(Duration::from_secs(30)), + syscall_budget: Duration::from_secs(10), + drain_budget: Duration::from_secs(120), + }; + static THREE_CLIENTS: Profile = Profile { name: "three-clients", clients: 3, @@ -1081,6 +1096,12 @@ mod tests { run_seeds(&ONE_CLIENT_FLAKY, 4); } + #[test] + #[ignore = "mounts FUSE: run with `cargo test -p pdfs-fuse --lib sim::run -- --ignored`"] + fn one_client_on_a_slow_link() { + run_seeds(&ONE_CLIENT_WIFI, 4); + } + #[test] #[ignore = "mounts FUSE: run with `cargo test -p pdfs-fuse --lib sim::run -- --ignored`"] fn three_clients_one_writer_each() { diff --git a/docs/MILESTONE-3.0.0-STATUS.md b/docs/MILESTONE-3.0.0-STATUS.md index 26a3b45..a755b35 100644 --- a/docs/MILESTONE-3.0.0-STATUS.md +++ b/docs/MILESTONE-3.0.0-STATUS.md @@ -32,13 +32,17 @@ Tracks `docs/MILESTONE-3.0.0.md`. Update it with every commit that moves a phase `finish_create` and `adopt_real_uid`; a landing create sets `remote_uid` on its row. 3. **Speed (ยง7)**: run independent ops in parallel, batch trashes and moves; measure 1,000 files and 100 folders on Wi-Fi against LAN (target: within 10 %). + - [x] The measurement: `a_thousand_files_drain_as_fast_on_wifi_as_on_lan` in `sim/daemon.rs`, + run with `PDFS_SIM_MEASURE=1`. It prints the times and asserts nothing yet. + - [ ] Baseline numbers, taken once the account run is done. 4. **Done-when checks**: - - [ ] Simulation passes on the Wi-Fi profile. + - [ ] Simulation passes on the Wi-Fi profile: `one_client_on_a_slow_link` is added, not yet + run. - [ ] Known-bug list in `sim/run.rs` is empty: B125 and B130 open; B129 and B132 fixed but unconfirmed. - [ ] A clean account run. The last one (2026-10-04) failed on B70 (fixed as B145) and mirror/mirror "busy syncing" (the script now retries); not confirmed yet. -5. **Release**: the 2.9.0 and 2.10.0 tags still wait for the user's go-ahead. +5. **Release**: 2.10.0 is tagged; the 2.9.0 tag still waits for the user's go-ahead. ## After 3.0.0