light_cache/
refresh.rs

1use crate::cache::DefaultHashBuilder;
2use crate::policy::TtlPolicy;
3use crate::LightCache;
4
5use std::future::Future;
6use std::hash::Hash;
7use std::time::Duration;
8
9/// A [`Refresher`] maps a key to a value asynchronously
10pub trait Refresher<K, V> {
11    type Error;
12
13    fn get(&self, key: K) -> impl Future<Output = Result<V, Self::Error>> + Send;
14}
15
16impl<K, V, F, Fut, E> Refresher<K, V> for F
17where
18    F: Fn(K) -> Fut,
19    Fut: Future<Output = Result<V, E>> + Send,
20{
21    type Error = E;
22
23    fn get(&self, key: K) -> impl Future<Output = Result<V, E>> + Send {
24        self(key)
25    }
26}
27
28/// A [`RefreshCache`] provides a simple interface for caching values with a time-to-live policy
29/// for any type that maps a key to a value asynchronously
30///
31/// This is a replacment for directly using [`LightCache`] 
32/// with a [`TtlPolicy`] and calling [`LightCache::get_or_try_insert`] everywhere
33pub struct RefreshCache<K, V, R> {
34    cache: LightCache<K, V, DefaultHashBuilder, TtlPolicy<K, V>>,
35    refresh: R,
36}
37
38impl<K, V, R, E> RefreshCache<K, V, R>
39where
40    K: Copy + Eq + Hash,
41    V: Clone + Sync,
42    R: Refresher<K, V, Error = E>,
43{
44    pub fn new(refresh: R, ttl: Duration) -> Self {
45        Self {
46            cache: LightCache::from_parts(TtlPolicy::new(ttl), Default::default()),
47            refresh,
48        }
49    }
50
51    pub async fn get(&self, key: K) -> Result<V, R::Error> {
52        self.cache.get_or_try_insert(key, || self.refresh.get(key)).await
53    }
54}