From 46e28cfac631256abb403769d276cd0554d4ade2 Mon Sep 17 00:00:00 2001 From: houseme Date: Sun, 28 Jun 2026 07:40:38 +0800 Subject: [PATCH] refactor(get): SF01 - use moka instead of dashmap for bucket cache Replace OnceLock + RwLock + HashMap with moka::sync::Cache for bucket validation cache. moka provides built-in TTL support and is already available in the workspace. Changes: - Add moka dependency to rustfs crate - Replace manual TTL management with moka's time_to_live - Simplify cache operations Closes rustfs/backlog#766 Co-Authored-By: heihutu --- rustfs/Cargo.toml | 1 + rustfs/src/storage/ecfs_extend.rs | 44 +++++++++++++------------------ 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/rustfs/Cargo.toml b/rustfs/Cargo.toml index e7ff97653..8c6fee0c8 100644 --- a/rustfs/Cargo.toml +++ b/rustfs/Cargo.toml @@ -100,6 +100,7 @@ rustfs-object-capacity = { workspace = true } rustfs-concurrency = { workspace = true } rustfs-scanner = { workspace = true } tempfile = { workspace = true } +moka = { workspace = true } # Async Runtime and Networking async-trait = { workspace = true } diff --git a/rustfs/src/storage/ecfs_extend.rs b/rustfs/src/storage/ecfs_extend.rs index 89e4e833b..474dbff7e 100644 --- a/rustfs/src/storage/ecfs_extend.rs +++ b/rustfs/src/storage/ecfs_extend.rs @@ -42,8 +42,8 @@ use s3s::{S3Error, S3ErrorCode, S3Response, S3Result}; use serde_urlencoded::from_bytes; use std::collections::HashMap; use std::ops::Add; -use std::sync::{Arc, OnceLock, RwLock}; -use std::time::{Duration, Instant}; +use std::sync::{Arc, OnceLock}; +use std::time::Duration; use time::OffsetDateTime; use time::format_description::well_known::Rfc3339; use time::{format_description::FormatItem, macros::format_description}; @@ -748,32 +748,33 @@ pub(crate) async fn has_replication_rules(bucket: &str, objects: &[ObjectToDelet /// Bucket 验证缓存:避免每次 GET 都执行 stat_volume() /// -/// 缓存 bucket 验证结果,TTL 内跳过重复验证。 +/// 使用 moka 缓存 bucket 验证结果,TTL 5 秒。 /// 写操作(delete/make bucket)会清除对应缓存。 -static BUCKET_VALIDATED_CACHE: OnceLock>> = OnceLock::new(); +static BUCKET_VALIDATED_CACHE: OnceLock> = OnceLock::new(); const BUCKET_VALIDATION_TTL: Duration = Duration::from_secs(5); +fn bucket_cache() -> &'static moka::sync::Cache { + BUCKET_VALIDATED_CACHE.get_or_init(|| { + moka::sync::Cache::builder() + .time_to_live(BUCKET_VALIDATION_TTL) + .max_capacity(1024) + .build() + }) +} + /// 清除指定 bucket 的验证缓存 pub fn invalidate_bucket_validation_cache(bucket: &str) { - if let Some(cache) = BUCKET_VALIDATED_CACHE.get() { - if let Ok(mut map) = cache.write() { - map.remove(bucket); - } - } + bucket_cache().invalidate(bucket); } /// 清除所有 bucket 验证缓存 pub fn invalidate_all_bucket_validation_cache() { - if let Some(cache) = BUCKET_VALIDATED_CACHE.get() { - if let Ok(mut map) = cache.write() { - map.clear(); - } - } + bucket_cache().invalidate_all(); } /// Helper function to get store and validate bucket exists /// -/// 使用短期缓存(5s TTL)避免每次 GET 都执行 stat_volume()。 +/// 使用 moka 缓存(5s TTL)避免每次 GET 都执行 stat_volume()。 /// 缓存命中时直接返回 store,不调用 get_bucket_info()。 pub(crate) async fn get_validated_store(bucket: &str) -> S3Result> { let Some(store) = runtime_sources::current_object_store_handle() else { @@ -781,13 +782,8 @@ pub(crate) async fn get_validated_store(bucket: &str) -> S3Result S3Result