do_memory_storage_redb/cache/
adapter.rs1use super::adaptive::{AdaptiveCache, AdaptiveCacheConfig, AdaptiveCacheMetrics};
9use super::traits::Cache;
10use super::types::CacheMetrics;
11use async_trait::async_trait;
12use uuid::Uuid;
13
14pub struct AdaptiveCacheAdapter {
41 inner: AdaptiveCache<()>,
42}
43
44impl AdaptiveCacheAdapter {
45 pub fn new(config: AdaptiveCacheConfig) -> Self {
47 Self {
48 inner: AdaptiveCache::new(config),
49 }
50 }
51
52 pub fn with_defaults() -> Self {
54 Self::new(AdaptiveCacheConfig::default())
55 }
56
57 pub fn inner(&self) -> &AdaptiveCache<()> {
59 &self.inner
60 }
61
62 pub async fn get_adaptive_metrics(&self) -> AdaptiveCacheMetrics {
64 self.inner.get_metrics().await
65 }
66
67 pub async fn hot_count(&self) -> usize {
69 self.inner.hot_count().await
70 }
71
72 pub async fn cold_count(&self) -> usize {
74 self.inner.cold_count().await
75 }
76
77 pub async fn len(&self) -> usize {
79 self.inner.len().await
80 }
81
82 pub async fn is_empty(&self) -> bool {
84 self.inner.is_empty().await
85 }
86}
87
88#[async_trait]
89impl Cache for AdaptiveCacheAdapter {
90 async fn record_access(&self, id: Uuid, hit: bool, _size_bytes: Option<usize>) -> bool {
91 let value = if hit { None } else { Some(()) };
95 self.inner.record_access(id, hit, value).await
96 }
97
98 async fn remove(&self, id: Uuid) {
99 self.inner.remove(id).await
100 }
101
102 async fn contains(&self, id: Uuid) -> bool {
103 self.inner.contains(id).await
104 }
105
106 async fn get_metrics(&self) -> CacheMetrics {
107 let adaptive_metrics = self.inner.get_metrics().await;
108 adaptive_metrics.base
109 }
110
111 async fn clear(&self) {
112 self.inner.clear().await
113 }
114
115 async fn cleanup_expired(&self) -> usize {
116 self.inner.cleanup_expired().await
117 }
118}
119
120impl From<AdaptiveCacheConfig> for AdaptiveCacheAdapter {
121 fn from(config: AdaptiveCacheConfig) -> Self {
122 Self::new(config)
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129 use std::time::Duration;
130
131 #[tokio::test]
132 async fn test_adapter_basic_operations() {
133 let config = AdaptiveCacheConfig {
134 max_size: 100,
135 default_ttl: Duration::from_secs(60),
136 ..Default::default()
137 };
138 let cache = AdaptiveCacheAdapter::new(config);
139
140 let id = Uuid::new_v4();
141
142 let result = cache.record_access(id, false, Some(100)).await;
144 assert!(!result); assert!(cache.contains(id).await);
148
149 let result = cache.record_access(id, true, None).await;
151 assert!(result); let metrics = cache.get_metrics().await;
155 assert_eq!(metrics.hits, 1);
156 assert_eq!(metrics.misses, 1);
157
158 cache.remove(id).await;
160 assert!(!cache.contains(id).await);
161 }
162
163 #[tokio::test]
164 async fn test_adapter_adaptive_features() {
165 let config = AdaptiveCacheConfig {
166 max_size: 100,
167 default_ttl: Duration::from_secs(60),
168 hot_threshold: 3,
169 ..Default::default()
170 };
171 let cache = AdaptiveCacheAdapter::new(config);
172
173 let id = Uuid::new_v4();
174
175 cache.record_access(id, false, None).await;
177
178 for _ in 0..5 {
180 cache.record_access(id, true, None).await;
181 }
182
183 assert!(cache.hot_count().await > 0);
185 }
186
187 #[tokio::test]
188 async fn test_adapter_cleanup() {
189 let config = AdaptiveCacheConfig {
190 max_size: 100,
191 default_ttl: Duration::from_millis(10), min_ttl: Duration::from_millis(1),
193 enable_background_cleanup: false,
194 ..Default::default()
195 };
196 let cache = AdaptiveCacheAdapter::new(config);
197
198 let id = Uuid::new_v4();
199 cache.record_access(id, false, None).await;
200
201 tokio::time::sleep(Duration::from_millis(50)).await;
203
204 let removed = cache.cleanup_expired().await;
206 assert!(removed > 0);
207 assert!(!cache.contains(id).await);
208 }
209}