mailguard_rs/
cache.rs

1#[cfg(feature = "cache")]
2use std::collections::HashMap;
3#[cfg(feature = "cache")]
4use std::sync::{Arc, Mutex};
5use std::time::{Duration, Instant};
6
7use crate::threat::ThreatType;
8
9/// 缓存条目
10#[derive(Debug, Clone)]
11pub struct CacheEntry {
12    pub threat_type: Option<ThreatType>,
13    pub timestamp: Instant,
14    pub ttl: Duration,
15}
16
17impl CacheEntry {
18    pub fn new(threat_type: Option<ThreatType>, ttl: Duration) -> Self {
19        Self {
20            threat_type,
21            timestamp: Instant::now(),
22            ttl,
23        }
24    }
25
26    pub fn is_expired(&self) -> bool {
27        self.timestamp.elapsed() > self.ttl
28    }
29}
30
31#[cfg(feature = "cache")]
32/// 内存缓存 (需要 cache feature)
33#[derive(Debug, Clone)]
34pub struct Cache {
35    inner: Arc<Mutex<HashMap<String, CacheEntry>>>,
36    default_ttl: Duration,
37}
38
39#[cfg(feature = "cache")]
40impl Cache {
41    pub fn new() -> Self {
42        Self {
43            inner: Arc::new(Mutex::new(HashMap::new())),
44            default_ttl: Duration::from_secs(300), // 5分钟默认TTL
45        }
46    }
47
48    pub fn with_ttl(ttl: Duration) -> Self {
49        Self {
50            inner: Arc::new(Mutex::new(HashMap::new())),
51            default_ttl: ttl,
52        }
53    }
54
55    /// 获取缓存条目
56    pub fn get(&self, key: &str) -> Option<Option<ThreatType>> {
57        let mut cache = self.inner.lock().unwrap();
58
59        if let Some(entry) = cache.get(key) {
60            if !entry.is_expired() {
61                return Some(entry.threat_type.clone());
62            } else {
63                // 移除过期条目
64                cache.remove(key);
65            }
66        }
67
68        None
69    }
70
71    /// 设置缓存条目
72    pub fn set(&self, key: String, threat_type: Option<ThreatType>) {
73        let entry = CacheEntry::new(threat_type, self.default_ttl);
74        let mut cache = self.inner.lock().unwrap();
75        cache.insert(key, entry);
76    }
77
78    /// 清理过期条目
79    pub fn cleanup_expired(&self) {
80        let mut cache = self.inner.lock().unwrap();
81        cache.retain(|_, entry| !entry.is_expired());
82    }
83
84    /// 获取缓存大小
85    pub fn size(&self) -> usize {
86        let cache = self.inner.lock().unwrap();
87        cache.len()
88    }
89
90    /// 清空缓存
91    pub fn clear(&self) {
92        let mut cache = self.inner.lock().unwrap();
93        cache.clear();
94    }
95}
96
97#[cfg(feature = "cache")]
98impl Default for Cache {
99    fn default() -> Self {
100        Self::new()
101    }
102}
103
104#[cfg(not(feature = "cache"))]
105/// 无操作缓存实现 (cache feature 未启用)
106#[derive(Debug, Clone)]
107pub struct Cache;
108
109#[cfg(not(feature = "cache"))]
110impl Cache {
111    pub fn new() -> Self {
112        Cache
113    }
114
115    pub fn with_ttl(_ttl: Duration) -> Self {
116        Cache
117    }
118
119    pub fn get(&self, _key: &str) -> Option<Option<ThreatType>> {
120        None
121    }
122
123    pub fn set(&self, _key: String, _threat_type: Option<ThreatType>) {
124        // 无操作
125    }
126
127    pub fn cleanup_expired(&self) {
128        // 无操作
129    }
130
131    pub fn size(&self) -> usize {
132        0
133    }
134
135    pub fn clear(&self) {
136        // 无操作
137    }
138}
139
140#[cfg(not(feature = "cache"))]
141impl Default for Cache {
142    fn default() -> Self {
143        Self::new()
144    }
145}