From 7e13e6cf0ca783fa2a89ee248cd6a8c479d50480 Mon Sep 17 00:00:00 2001 From: jiangkoumo Date: Sat, 24 Oct 2026 03:36:41 +0000 Subject: [PATCH] test(persistence): retry Busy reclamation jobs in immutable_reads_under_reclamation The Store binds no busy handler, so reclaim_space can be refused Busy without effect while the concurrent reader holds its snapshot. The test unwrapped that outcome and failed intermittently (4 of 80 local runs, and PR #402 CI). Treat Busy as the documented refused job and run a later one, bounded by JOBS. --- .../tests/immutable_reads_under_reclamation.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/core/crates/layerfs-persistence/tests/immutable_reads_under_reclamation.rs b/core/crates/layerfs-persistence/tests/immutable_reads_under_reclamation.rs index 1b3a36cde..3af44c164 100644 --- a/core/crates/layerfs-persistence/tests/immutable_reads_under_reclamation.rs +++ b/core/crates/layerfs-persistence/tests/immutable_reads_under_reclamation.rs @@ -159,9 +159,19 @@ fn immutable_reads_are_unchanged_while_free_pages_are_reclaimed() { let done = AtomicBool::new(false); let (jobs, rounds, reclaimed) = std::thread::scope(|scope| { let reclaim = scope.spawn(|| { - let (mut jobs, mut reclaimed) = (0, 0); + let (mut jobs, mut reclaimed, mut busy) = (0, 0, 0); while jobs < JOBS { - let job = writer.reclaim_space(1).unwrap(); + // The Store binds no busy handler, so a job that meets the + // concurrent reader's snapshot is refused `Busy` without + // effect; the documented caller response is a later job. + let job = match writer.reclaim_space(1) { + Err(PersistenceError::Busy) if busy < JOBS => { + busy += 1; + std::thread::yield_now(); + continue; + } + other => other.unwrap(), + }; jobs += 1; reclaimed += job.reclaimed_pages; if job.remaining_free_pages == 0 {