use super::adaptive::{AdaptiveCache, AdaptiveCacheConfig, AdaptiveCacheMetrics};
use super::traits::Cache;
use super::types::CacheMetrics;
use async_trait::async_trait;
use uuid::Uuid;
pub struct AdaptiveCacheAdapter {
inner: AdaptiveCache<()>,
}
impl AdaptiveCacheAdapter {
pub fn new(config: AdaptiveCacheConfig) -> Self {
Self {
inner: AdaptiveCache::new(config),
}
}
pub fn with_defaults() -> Self {
Self::new(AdaptiveCacheConfig::default())
}
pub fn inner(&self) -> &AdaptiveCache<()> {
&self.inner
}
pub async fn get_adaptive_metrics(&self) -> AdaptiveCacheMetrics {
self.inner.get_metrics().await
}
pub async fn hot_count(&self) -> usize {
self.inner.hot_count().await
}
pub async fn cold_count(&self) -> usize {
self.inner.cold_count().await
}
pub async fn len(&self) -> usize {
self.inner.len().await
}
pub async fn is_empty(&self) -> bool {
self.inner.is_empty().await
}
}
#[async_trait]
impl Cache for AdaptiveCacheAdapter {
async fn record_access(&self, id: Uuid, hit: bool, _size_bytes: Option<usize>) -> bool {
let value = if hit { None } else { Some(()) };
self.inner.record_access(id, hit, value).await
}
async fn remove(&self, id: Uuid) {
self.inner.remove(id).await
}
async fn contains(&self, id: Uuid) -> bool {
self.inner.contains(id).await
}
async fn get_metrics(&self) -> CacheMetrics {
let adaptive_metrics = self.inner.get_metrics().await;
adaptive_metrics.base
}
async fn clear(&self) {
self.inner.clear().await
}
async fn cleanup_expired(&self) -> usize {
self.inner.cleanup_expired().await
}
}
impl From<AdaptiveCacheConfig> for AdaptiveCacheAdapter {
fn from(config: AdaptiveCacheConfig) -> Self {
Self::new(config)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[tokio::test]
async fn test_adapter_basic_operations() {
let config = AdaptiveCacheConfig {
max_size: 100,
default_ttl: Duration::from_secs(60),
..Default::default()
};
let cache = AdaptiveCacheAdapter::new(config);
let id = Uuid::new_v4();
let result = cache.record_access(id, false, Some(100)).await;
assert!(!result);
assert!(cache.contains(id).await);
let result = cache.record_access(id, true, None).await;
assert!(result);
let metrics = cache.get_metrics().await;
assert_eq!(metrics.hits, 1);
assert_eq!(metrics.misses, 1);
cache.remove(id).await;
assert!(!cache.contains(id).await);
}
#[tokio::test]
async fn test_adapter_adaptive_features() {
let config = AdaptiveCacheConfig {
max_size: 100,
default_ttl: Duration::from_secs(60),
hot_threshold: 3,
..Default::default()
};
let cache = AdaptiveCacheAdapter::new(config);
let id = Uuid::new_v4();
cache.record_access(id, false, None).await;
for _ in 0..5 {
cache.record_access(id, true, None).await;
}
assert!(cache.hot_count().await > 0);
}
#[tokio::test]
async fn test_adapter_cleanup() {
let config = AdaptiveCacheConfig {
max_size: 100,
default_ttl: Duration::from_millis(10), min_ttl: Duration::from_millis(1),
enable_background_cleanup: false,
..Default::default()
};
let cache = AdaptiveCacheAdapter::new(config);
let id = Uuid::new_v4();
cache.record_access(id, false, None).await;
tokio::time::sleep(Duration::from_millis(50)).await;
let removed = cache.cleanup_expired().await;
assert!(removed > 0);
assert!(!cache.contains(id).await);
}
}