From a3c32b5b1866c91d5101a8a5f389681a0c76b838 Mon Sep 17 00:00:00 2001 From: dispather <62810211+dispather@users.noreply.github.com> Date: Wed, 5 Aug 2026 23:59:36 +0900 Subject: [PATCH] fix: don't hold the storage mapping cache guard across the database query `DashMap::get` hands out a read guard on the map shard, and taking the write lock for `insert` parks the calling thread rather than just the task. Holding that guard across the storage mapping query therefore blocks any worker that inserts into the same shard while the query is in flight; once that starves the runtime, nothing polls the reactor, the query never completes and the guard is never released, so the process stops serving until it is restarted. The stale-refresh and cache-miss branches had identical tails, so they collapse into a single path once the guard is dropped before the query. Signed-off-by: dispather <62810211+dispather@users.noreply.github.com> --- src/storage_mapping.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/storage_mapping.rs b/src/storage_mapping.rs index 2d704a8..8eb7c14 100644 --- a/src/storage_mapping.rs +++ b/src/storage_mapping.rs @@ -78,24 +78,28 @@ impl StorageMapping { &self, storage: u32, ) -> Result, DatabaseError> { + // Note: the `Ref` handed out by `DashMap::get` is a read guard on the map shard, and + // taking the write lock for `insert` blocks the calling *thread*, not just the task. + // Holding the guard across the `.await` below therefore parks any runtime worker that + // tries to insert into the same shard while this query is in flight; if that starves + // the runtime, nothing polls the reactor, the query never completes and the guard is + // never released. Keep every guard in this function strictly await-free. if let Some(cached) = self.cache.get(&storage) { if cached.is_valid() { return Ok(cached); } cached.prepare_update(true); - let users = self - .load_storage_mapping(storage) - .await - .inspect_err(|_| cached.prepare_update(false))?; - - drop(cached); - let cached = CachedAccess::new(users); - self.cache.insert(storage, cached); - return Ok(self.cache.get(&storage).unwrap()); } - let users = self.load_storage_mapping(storage).await?; + let users = self + .load_storage_mapping(storage) + .await + .inspect_err(|_| { + if let Some(cached) = self.cache.get(&storage) { + cached.prepare_update(false); + } + })?; self.cache.insert(storage, CachedAccess::new(users)); Ok(self.cache.get(&storage).unwrap())