From cd98c050b62a4f2e901d47ec040a1f08818eeca2 Mon Sep 17 00:00:00 2001 From: rustmailer Date: Tue, 23 Jun 2026 23:28:33 +0800 Subject: [PATCH] fix(blob): invalidate FilePool after GC to prevent stale reads --- crates/blob/src/engine.rs | 8 ++++++++ crates/blob/src/segment.rs | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/blob/src/engine.rs b/crates/blob/src/engine.rs index 18d13b8..126dc9b 100644 --- a/crates/blob/src/engine.rs +++ b/crates/blob/src/engine.rs @@ -299,6 +299,14 @@ impl Engine { let result = gc::gc_account(&account_dir, self.config.gc_deleted_ratio)?; + // Invalidate FilePool for GC'd segments (they were rewritten via rename) + if let Some(ref stats) = result { + let accounts = self.accounts.read().unwrap(); + if let Some(handle) = accounts.get(account_id) { + handle.invalidate_file_cache(stats.segment_id); + } + } + for bid in 0..crate::types::BUCKET_COUNT { self.cache.invalidate(account_id, bid); } diff --git a/crates/blob/src/segment.rs b/crates/blob/src/segment.rs index 0d7b162..30e4c5a 100644 --- a/crates/blob/src/segment.rs +++ b/crates/blob/src/segment.rs @@ -273,7 +273,6 @@ impl SegmentReader { /// Read a single entry at the given offset using a pre-opened File (via Mutex). /// This avoids the per-read File::open cost for hot segments. pub fn read_entry_at_file(&self, offset: u64, file: &Mutex) -> Result<(Entry, u64)> { - use std::io::{Read, Seek, SeekFrom}; let mut file = file.lock().unwrap();