mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-22 04:16:38 +00:00
fix(cache): wire trusted-proxy cache and remove stale cache traces (#2581)
This commit is contained in:
@@ -14,62 +14,114 @@
|
||||
|
||||
//! High-performance cache implementation for proxy validation results using Moka.
|
||||
|
||||
use moka::future::Cache;
|
||||
use moka::sync::Cache;
|
||||
use std::net::IpAddr;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::ProxyMetrics;
|
||||
|
||||
/// Cache for storing IP validation results.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IpValidationCache {
|
||||
/// The underlying Moka cache.
|
||||
cache: Cache<IpAddr, bool>,
|
||||
/// Configured capacity.
|
||||
capacity: usize,
|
||||
/// Whether the cache is enabled.
|
||||
enabled: bool,
|
||||
/// Optional metrics collector for cache activity.
|
||||
metrics: Option<ProxyMetrics>,
|
||||
}
|
||||
|
||||
impl IpValidationCache {
|
||||
/// Creates a new `IpValidationCache` using Moka.
|
||||
pub fn new(capacity: usize, ttl: Duration, enabled: bool) -> Self {
|
||||
pub fn new(capacity: usize, ttl: Duration, enabled: bool, metrics: Option<ProxyMetrics>) -> Self {
|
||||
let cache = Cache::builder().max_capacity(capacity as u64).time_to_live(ttl).build();
|
||||
|
||||
Self { cache, enabled }
|
||||
let this = Self {
|
||||
cache,
|
||||
capacity,
|
||||
enabled,
|
||||
metrics,
|
||||
};
|
||||
this.update_cache_size_metric();
|
||||
this
|
||||
}
|
||||
|
||||
/// Checks if an IP is trusted, using the cache if available.
|
||||
pub async fn is_trusted(&self, ip: &IpAddr, validator: impl FnOnce(&IpAddr) -> bool) -> bool {
|
||||
pub fn is_trusted(&self, ip: &IpAddr, validator: impl FnOnce(&IpAddr) -> bool) -> bool {
|
||||
if !self.enabled {
|
||||
return validator(ip);
|
||||
}
|
||||
|
||||
// Attempt to get the result from cache.
|
||||
if let Some(is_trusted) = self.cache.get(ip).await {
|
||||
metrics::counter!("rustfs_trusted_proxy_cache_hits").increment(1);
|
||||
if let Some(is_trusted) = self.cache.get(ip) {
|
||||
self.record_cache_hit();
|
||||
return is_trusted;
|
||||
}
|
||||
|
||||
// Cache miss: perform validation and update cache.
|
||||
metrics::counter!("rustfs_trusted_proxy_cache_misses").increment(1);
|
||||
// Cache miss: perform validation. Only positive trust decisions are cached
|
||||
// to avoid polluting the cache with one-off untrusted client IPs.
|
||||
self.record_cache_miss();
|
||||
let is_trusted = validator(ip);
|
||||
self.cache.insert(*ip, is_trusted).await;
|
||||
if is_trusted {
|
||||
self.cache.insert(*ip, is_trusted);
|
||||
self.update_cache_size_metric();
|
||||
}
|
||||
|
||||
is_trusted
|
||||
}
|
||||
|
||||
/// Clears all entries from the cache.
|
||||
pub async fn clear(&self) {
|
||||
pub fn clear(&self) {
|
||||
self.cache.invalidate_all();
|
||||
metrics::gauge!("rustfs_trusted_proxy_cache_size").set(0.0);
|
||||
self.cache.run_pending_tasks();
|
||||
self.update_cache_size_metric();
|
||||
}
|
||||
|
||||
/// Runs pending cache maintenance tasks and refreshes size metrics.
|
||||
pub fn run_maintenance(&self) {
|
||||
if !self.enabled {
|
||||
return;
|
||||
}
|
||||
|
||||
self.cache.run_pending_tasks();
|
||||
self.update_cache_size_metric();
|
||||
}
|
||||
|
||||
/// Returns statistics about the current state of the cache.
|
||||
pub fn stats(&self) -> CacheStats {
|
||||
if self.enabled {
|
||||
self.cache.run_pending_tasks();
|
||||
}
|
||||
|
||||
let entry_count = self.cache.entry_count();
|
||||
|
||||
CacheStats {
|
||||
size: entry_count as usize,
|
||||
// Moka doesn't expose max_capacity directly in a simple way after build,
|
||||
// but we can track it if needed.
|
||||
capacity: 0,
|
||||
capacity: self.capacity,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether the cache is enabled.
|
||||
pub fn is_enabled(&self) -> bool {
|
||||
self.enabled
|
||||
}
|
||||
|
||||
fn record_cache_hit(&self) {
|
||||
if let Some(metrics) = &self.metrics {
|
||||
metrics.record_cache_hit();
|
||||
}
|
||||
}
|
||||
|
||||
fn record_cache_miss(&self) {
|
||||
if let Some(metrics) = &self.metrics {
|
||||
metrics.record_cache_miss();
|
||||
}
|
||||
}
|
||||
|
||||
fn update_cache_size_metric(&self) {
|
||||
if let Some(metrics) = &self.metrics {
|
||||
metrics.set_cache_size(self.cache.entry_count() as usize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user