use crate::cache::DefaultHashBuilder;
use crate::policy::TtlPolicy;
use crate::LightCache;
use std::future::Future;
use std::hash::Hash;
use std::time::Duration;
pub trait Refresher<K, V> {
type Error;
fn get(&self, key: K) -> impl Future<Output = Result<V, Self::Error>> + Send;
}
impl<K, V, F, Fut, E> Refresher<K, V> for F
where
F: Fn(K) -> Fut,
Fut: Future<Output = Result<V, E>> + Send,
{
type Error = E;
fn get(&self, key: K) -> impl Future<Output = Result<V, E>> + Send {
self(key)
}
}
pub struct RefreshCache<K, V, R> {
cache: LightCache<K, V, DefaultHashBuilder, TtlPolicy<K, V>>,
refresh: R,
}
impl<K, V, R, E> RefreshCache<K, V, R>
where
K: Copy + Eq + Hash,
V: Clone + Sync,
R: Refresher<K, V, Error = E>,
{
pub fn new(refresh: R, ttl: Duration) -> Self {
Self {
cache: LightCache::from_parts(TtlPolicy::new(ttl), Default::default()),
refresh,
}
}
pub async fn get(&self, key: K) -> Result<V, R::Error> {
self.cache.get_or_try_insert(key, || self.refresh.get(key)).await
}
}