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
9pub 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
28pub 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}