use std::fmt::Debug;
use std::sync::Arc;
use crate::SizeError;
use crate::tier::DynCacheTier;
use crate::{CacheEntry, CacheTier, Error};
pub struct DynamicCache<K, V>(Arc<DynCacheTier<'static, K, V>>);
impl<K, V> DynamicCache<K, V> {
pub fn new<T>(strategy: T) -> Self
where
T: CacheTier<K, V> + Send + Sync + 'static,
{
Self(DynCacheTier::new_arc(strategy))
}
}
impl<K, V> Debug for DynamicCache<K, V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DynamicCache").finish()
}
}
impl<K, V> Clone for DynamicCache<K, V> {
fn clone(&self) -> Self {
Self(Arc::clone(&self.0))
}
}
impl<K: Send + Sync, V: Send> CacheTier<K, V> for DynamicCache<K, V> {
async fn get(&self, key: &K) -> Result<Option<CacheEntry<V>>, Error> {
self.0.get(key).await
}
async fn insert(&self, key: K, entry: CacheEntry<V>) -> Result<(), Error> {
self.0.insert(key, entry).await
}
async fn invalidate(&self, key: &K) -> Result<(), Error> {
self.0.invalidate(key).await
}
async fn clear(&self) -> Result<(), Error> {
self.0.clear().await
}
async fn len(&self) -> Result<u64, SizeError> {
self.0.len().await
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::MockCache;
#[cfg_attr(miri, ignore)]
#[tokio::test]
async fn clone_shares_state() {
let cache = MockCache::<String, i32>::new();
let dynamic = DynamicCache::new(cache);
let clone = dynamic.clone();
dynamic.insert("key".to_string(), CacheEntry::new(42)).await.unwrap();
let entry = clone.get(&"key".to_string()).await.unwrap().unwrap();
assert_eq!(*entry.value(), 42);
}
}