cached/stores/
timed_sized.rs

1use std::cmp::Eq;
2use std::hash::Hash;
3
4use web_time::Instant;
5
6#[cfg(feature = "async")]
7use {super::CachedAsync, async_trait::async_trait, futures::Future};
8
9use crate::{stores::timed::Status, CloneCached};
10
11use super::{Cached, SizedCache};
12
13/// Timed LRU Cache
14///
15/// Stores a limited number of values,
16/// evicting expired and least-used entries.
17/// Time expiration is determined based on entry insertion time..
18/// The TTL of an entry is not updated when retrieved.
19///
20/// Note: This cache is in-memory only
21#[derive(Clone, Debug)]
22pub struct TimedSizedCache<K, V> {
23    pub(super) store: SizedCache<K, (Instant, V)>,
24    pub(super) size: usize,
25    pub(super) seconds: u64,
26    pub(super) hits: u64,
27    pub(super) misses: u64,
28    pub(super) refresh: bool,
29}
30
31impl<K: Hash + Eq + Clone, V> TimedSizedCache<K, V> {
32    /// Creates a new `SizedCache` with a given size limit and pre-allocated backing data
33    #[must_use]
34    pub fn with_size_and_lifespan(size: usize, seconds: u64) -> TimedSizedCache<K, V> {
35        Self::with_size_and_lifespan_and_refresh(size, seconds, false)
36    }
37
38    /// Creates a new `SizedCache` with a given size limit and pre-allocated backing data.
39    /// Also set if the ttl should be refreshed on retrieving
40    ///
41    /// # Panics
42    ///
43    /// Will panic if size is 0
44    #[must_use]
45    pub fn with_size_and_lifespan_and_refresh(
46        size: usize,
47        seconds: u64,
48        refresh: bool,
49    ) -> TimedSizedCache<K, V> {
50        if size == 0 {
51            panic!("`size` of `TimedSizedCache` must be greater than zero.");
52        }
53        TimedSizedCache {
54            store: SizedCache::with_size(size),
55            size,
56            seconds,
57            hits: 0,
58            misses: 0,
59            refresh,
60        }
61    }
62
63    /// Creates a new `TimedSizedCache` with a specified lifespan and a given size limit and pre-allocated backing data
64    ///
65    /// # Errors
66    ///
67    /// Will return a `std::io::Error`, depending on the error
68    pub fn try_with_size_and_lifespan(
69        size: usize,
70        seconds: u64,
71    ) -> std::io::Result<TimedSizedCache<K, V>> {
72        if size == 0 {
73            // EINVAL
74            return Err(std::io::Error::from_raw_os_error(22));
75        }
76        Ok(TimedSizedCache {
77            store: SizedCache::try_with_size(size)?,
78            size,
79            seconds,
80            hits: 0,
81            misses: 0,
82            refresh: false,
83        })
84    }
85
86    fn iter_order(&self) -> impl Iterator<Item = &(K, (Instant, V))> {
87        let max_seconds = self.seconds;
88        self.store
89            .iter_order()
90            .filter(move |(_k, stamped)| stamped.0.elapsed().as_secs() < max_seconds)
91    }
92
93    /// Return an iterator of keys in the current order from most
94    /// to least recently used.
95    /// Items passed their expiration seconds will be excluded.
96    pub fn key_order(&self) -> impl Iterator<Item = &K> {
97        self.iter_order().map(|(k, _v)| k)
98    }
99
100    /// Return an iterator of timestamped values in the current order
101    /// from most to least recently used.
102    /// Items passed their expiration seconds will be excluded.
103    pub fn value_order(&self) -> impl Iterator<Item = &(Instant, V)> {
104        self.iter_order().map(|(_k, v)| v)
105    }
106
107    /// Returns if the lifetime is refreshed when the value is retrieved
108    #[must_use]
109    pub fn refresh(&self) -> bool {
110        self.refresh
111    }
112
113    /// Sets if the lifetime is refreshed when the value is retrieved
114    pub fn set_refresh(&mut self, refresh: bool) {
115        self.refresh = refresh;
116    }
117
118    /// Returns a reference to the cache's `store`
119    #[must_use]
120    pub fn get_store(&self) -> &SizedCache<K, (Instant, V)> {
121        &self.store
122    }
123
124    /// Remove any expired values from the cache
125    pub fn flush(&mut self) {
126        let seconds = self.seconds;
127        self.store
128            .retain(|_, (instant, _)| instant.elapsed().as_secs() < seconds);
129    }
130
131    fn status<Q>(&mut self, key: &Q) -> Status
132    where
133        K: std::borrow::Borrow<Q>,
134        Q: std::hash::Hash + Eq + ?Sized,
135    {
136        let mut val = self.store.get_mut_if(key, |_| true);
137        if let Some(&mut (instant, _)) = val.as_mut() {
138            if instant.elapsed().as_secs() < self.seconds {
139                if self.refresh {
140                    *instant = Instant::now();
141                }
142                Status::Found
143            } else {
144                Status::Expired
145            }
146        } else {
147            Status::NotFound
148        }
149    }
150}
151
152impl<K: Hash + Eq + Clone, V> Cached<K, V> for TimedSizedCache<K, V> {
153    fn cache_get<Q>(&mut self, key: &Q) -> Option<&V>
154    where
155        K: std::borrow::Borrow<Q>,
156        Q: std::hash::Hash + Eq + ?Sized,
157    {
158        match self.status(key) {
159            Status::NotFound => {
160                self.misses += 1;
161                None
162            }
163            Status::Found => {
164                self.hits += 1;
165                self.store.cache_get(key).map(|stamped| &stamped.1)
166            }
167            Status::Expired => {
168                self.misses += 1;
169                self.store.cache_remove(key);
170                None
171            }
172        }
173    }
174
175    fn cache_get_mut<Q>(&mut self, key: &Q) -> std::option::Option<&mut V>
176    where
177        K: std::borrow::Borrow<Q>,
178        Q: std::hash::Hash + Eq + ?Sized,
179    {
180        match self.status(key) {
181            Status::NotFound => {
182                self.misses += 1;
183                None
184            }
185            Status::Found => {
186                self.hits += 1;
187                self.store.cache_get_mut(key).map(|stamped| &mut stamped.1)
188            }
189            Status::Expired => {
190                self.misses += 1;
191                self.store.cache_remove(key);
192                None
193            }
194        }
195    }
196
197    fn cache_get_or_set_with<F: FnOnce() -> V>(&mut self, key: K, f: F) -> &mut V {
198        let setter = || (Instant::now(), f());
199        let max_seconds = self.seconds;
200        let (was_present, was_valid, stamped) =
201            self.store.get_or_set_with_if(key, setter, |stamped| {
202                stamped.0.elapsed().as_secs() < max_seconds
203            });
204        if was_present && was_valid {
205            if self.refresh {
206                stamped.0 = Instant::now();
207            }
208            self.hits += 1;
209        } else {
210            self.misses += 1;
211        }
212        &mut stamped.1
213    }
214
215    fn cache_try_get_or_set_with<F: FnOnce() -> Result<V, E>, E>(
216        &mut self,
217        key: K,
218        f: F,
219    ) -> Result<&mut V, E> {
220        let setter = || Ok((Instant::now(), f()?));
221        let max_seconds = self.seconds;
222        let (was_present, was_valid, stamped) =
223            self.store.try_get_or_set_with_if(key, setter, |stamped| {
224                stamped.0.elapsed().as_secs() < max_seconds
225            })?;
226        if was_present && was_valid {
227            if self.refresh {
228                stamped.0 = Instant::now();
229            }
230            self.hits += 1;
231        } else {
232            self.misses += 1;
233        }
234        Ok(&mut stamped.1)
235    }
236
237    fn cache_set(&mut self, key: K, val: V) -> Option<V> {
238        let stamped = self.store.cache_set(key, (Instant::now(), val));
239        stamped.and_then(|(instant, v)| {
240            if instant.elapsed().as_secs() < self.seconds {
241                Some(v)
242            } else {
243                None
244            }
245        })
246    }
247
248    fn cache_remove<Q>(&mut self, k: &Q) -> Option<V>
249    where
250        K: std::borrow::Borrow<Q>,
251        Q: std::hash::Hash + Eq + ?Sized,
252    {
253        let stamped = self.store.cache_remove(k);
254        stamped.and_then(|(instant, v)| {
255            if instant.elapsed().as_secs() < self.seconds {
256                Some(v)
257            } else {
258                None
259            }
260        })
261    }
262    fn cache_clear(&mut self) {
263        self.store.cache_clear();
264    }
265    fn cache_reset(&mut self) {
266        self.cache_clear();
267    }
268    fn cache_reset_metrics(&mut self) {
269        self.misses = 0;
270        self.hits = 0;
271    }
272    fn cache_size(&self) -> usize {
273        self.store.cache_size()
274    }
275    fn cache_hits(&self) -> Option<u64> {
276        Some(self.hits)
277    }
278    fn cache_misses(&self) -> Option<u64> {
279        Some(self.misses)
280    }
281    fn cache_capacity(&self) -> Option<usize> {
282        Some(self.size)
283    }
284    fn cache_lifespan(&self) -> Option<u64> {
285        Some(self.seconds)
286    }
287    fn cache_set_lifespan(&mut self, seconds: u64) -> Option<u64> {
288        let old = self.seconds;
289        self.seconds = seconds;
290        Some(old)
291    }
292}
293
294impl<K: Hash + Eq + Clone, V: Clone> CloneCached<K, V> for TimedSizedCache<K, V> {
295    fn cache_get_expired<Q>(&mut self, k: &Q) -> (Option<V>, bool)
296    where
297        K: std::borrow::Borrow<Q>,
298        Q: std::hash::Hash + Eq + ?Sized,
299    {
300        match self.status(k) {
301            Status::NotFound => {
302                self.misses += 1;
303                (None, false)
304            }
305            Status::Found => {
306                self.hits += 1;
307                (
308                    self.store.cache_get(k).map(|stamped| stamped.1.clone()),
309                    false,
310                )
311            }
312            Status::Expired => {
313                self.misses += 1;
314                (self.store.cache_remove(k).map(|stamped| stamped.1), true)
315            }
316        }
317    }
318}
319
320#[cfg(feature = "async")]
321#[async_trait]
322impl<K, V> CachedAsync<K, V> for TimedSizedCache<K, V>
323where
324    K: Hash + Eq + Clone + Send,
325{
326    async fn get_or_set_with<F, Fut>(&mut self, key: K, f: F) -> &mut V
327    where
328        V: Send,
329        F: FnOnce() -> Fut + Send,
330        Fut: Future<Output = V> + Send,
331    {
332        let setter = || async { (Instant::now(), f().await) };
333        let max_seconds = self.seconds;
334        let (was_present, was_valid, stamped) = self
335            .store
336            .get_or_set_with_if_async(key, setter, |stamped| {
337                stamped.0.elapsed().as_secs() < max_seconds
338            })
339            .await;
340        if was_present && was_valid {
341            if self.refresh {
342                stamped.0 = Instant::now();
343            }
344            self.hits += 1;
345        } else {
346            self.misses += 1;
347        }
348        &mut stamped.1
349    }
350
351    async fn try_get_or_set_with<F, Fut, E>(&mut self, key: K, f: F) -> Result<&mut V, E>
352    where
353        V: Send,
354        F: FnOnce() -> Fut + Send,
355        Fut: Future<Output = Result<V, E>> + Send,
356    {
357        let setter = || async {
358            let new_val = f().await?;
359            Ok((Instant::now(), new_val))
360        };
361        let max_seconds = self.seconds;
362        let (was_present, was_valid, stamped) = self
363            .store
364            .try_get_or_set_with_if_async(key, setter, |stamped| {
365                stamped.0.elapsed().as_secs() < max_seconds
366            })
367            .await?;
368        if was_present && was_valid {
369            if self.refresh {
370                stamped.0 = Instant::now();
371            }
372            self.hits += 1;
373        } else {
374            self.misses += 1;
375        }
376        Ok(&mut stamped.1)
377    }
378}
379
380#[cfg(test)]
381/// Cache store tests
382mod tests {
383    use std::{thread::sleep, time::Duration};
384
385    use super::*;
386
387    #[test]
388    fn timed_sized_cache() {
389        let mut c = TimedSizedCache::with_size_and_lifespan(5, 2);
390        assert!(c.cache_get(&1).is_none());
391        let misses = c.cache_misses().unwrap();
392        assert_eq!(1, misses);
393
394        assert_eq!(c.cache_set(1, 100), None);
395        assert!(c.cache_get(&1).is_some());
396        let hits = c.cache_hits().unwrap();
397        let misses = c.cache_misses().unwrap();
398        assert_eq!(1, hits);
399        assert_eq!(1, misses);
400
401        assert_eq!(c.cache_set(2, 100), None);
402        assert_eq!(c.cache_set(3, 100), None);
403        assert_eq!(c.cache_set(4, 100), None);
404        assert_eq!(c.cache_set(5, 100), None);
405
406        assert_eq!(c.key_order().copied().collect::<Vec<_>>(), [5, 4, 3, 2, 1]);
407
408        sleep(Duration::new(1, 0));
409
410        assert_eq!(c.cache_set(6, 100), None);
411        assert_eq!(c.cache_set(7, 100), None);
412
413        assert_eq!(c.key_order().copied().collect::<Vec<_>>(), [7, 6, 5, 4, 3]);
414
415        assert!(c.cache_get(&2).is_none());
416        assert!(c.cache_get(&3).is_some());
417
418        assert_eq!(c.key_order().copied().collect::<Vec<_>>(), [3, 7, 6, 5, 4]);
419
420        assert_eq!(2, c.cache_misses().unwrap());
421        assert_eq!(5, c.cache_size());
422
423        sleep(Duration::new(1, 0));
424
425        assert!(c.cache_get(&1).is_none());
426        assert!(c.cache_get(&2).is_none());
427        assert!(c.cache_get(&3).is_none());
428        assert!(c.cache_get(&4).is_none());
429        assert!(c.cache_get(&5).is_none());
430        assert!(c.cache_get(&6).is_some());
431        assert!(c.cache_get(&7).is_some());
432
433        assert_eq!(7, c.cache_misses().unwrap());
434
435        assert!(c.cache_set(1, 100).is_none());
436        assert!(c.cache_set(2, 100).is_none());
437        assert!(c.cache_set(3, 100).is_none());
438        assert_eq!(c.key_order().copied().collect::<Vec<_>>(), [3, 2, 1, 7, 6]);
439
440        sleep(Duration::new(1, 0));
441
442        assert!(c.cache_get(&1).is_some());
443        assert!(c.cache_get(&2).is_some());
444        assert!(c.cache_get(&3).is_some());
445        assert!(c.cache_get(&4).is_none());
446        assert!(c.cache_get(&5).is_none());
447        assert!(c.cache_get(&6).is_none());
448        assert!(c.cache_get(&7).is_none());
449
450        assert_eq!(11, c.cache_misses().unwrap());
451
452        let mut c = TimedSizedCache::with_size_and_lifespan(5, 0);
453        let mut ticker = 0;
454        let setter = || {
455            let v = ticker;
456            ticker += 1;
457            v
458        };
459        assert_eq!(c.cache_get_or_set_with(1, setter), &0);
460        let setter = || {
461            let v = ticker;
462            ticker += 1;
463            v
464        };
465        assert_eq!(c.cache_get_or_set_with(1, setter), &1);
466    }
467
468    #[test]
469    fn timed_cache_refresh() {
470        let mut c = TimedSizedCache::with_size_and_lifespan_and_refresh(2, 2, true);
471        assert!(c.refresh());
472        assert_eq!(c.cache_get(&1), None);
473        let misses = c.cache_misses().unwrap();
474        assert_eq!(1, misses);
475
476        assert_eq!(c.cache_set(1, 100), None);
477        assert_eq!(c.cache_get(&1), Some(&100));
478        let hits = c.cache_hits().unwrap();
479        let misses = c.cache_misses().unwrap();
480        assert_eq!(1, hits);
481        assert_eq!(1, misses);
482
483        assert_eq!(c.cache_set(2, 200), None);
484        assert_eq!(c.cache_get(&2), Some(&200));
485        sleep(Duration::new(1, 0));
486        assert_eq!(c.cache_get(&1), Some(&100));
487        sleep(Duration::new(1, 0));
488        assert_eq!(c.cache_get(&1), Some(&100));
489        assert_eq!(c.cache_get(&2), None);
490    }
491
492    #[test]
493    fn try_new() {
494        let c: std::io::Result<TimedSizedCache<i32, i32>> =
495            TimedSizedCache::try_with_size_and_lifespan(0, 2);
496        assert_eq!(c.unwrap_err().raw_os_error(), Some(22));
497    }
498
499    #[test]
500    fn clear() {
501        let mut c = TimedSizedCache::with_size_and_lifespan(3, 3600);
502
503        assert_eq!(c.cache_set(1, 100), None);
504        assert_eq!(c.cache_set(2, 200), None);
505        assert_eq!(c.cache_set(3, 300), None);
506        c.cache_clear();
507
508        assert_eq!(0, c.cache_size());
509    }
510
511    #[test]
512    fn reset() {
513        let init_capacity = 1;
514        let mut c = TimedSizedCache::with_size_and_lifespan(init_capacity, 100);
515        assert_eq!(c.cache_set(1, 100), None);
516        assert_eq!(c.cache_set(2, 200), None);
517        assert_eq!(c.cache_set(3, 300), None);
518        assert!(init_capacity <= c.store.capacity);
519
520        c.cache_reset();
521        assert!(init_capacity <= c.store.capacity);
522    }
523
524    #[test]
525    fn remove() {
526        let mut c = TimedSizedCache::with_size_and_lifespan(3, 3600);
527
528        assert_eq!(c.cache_set(1, 100), None);
529        assert_eq!(c.cache_set(2, 200), None);
530        assert_eq!(c.cache_set(3, 300), None);
531
532        assert_eq!(Some(100), c.cache_remove(&1));
533        assert_eq!(2, c.cache_size());
534
535        assert_eq!(Some(200), c.cache_remove(&2));
536        assert_eq!(1, c.cache_size());
537
538        assert_eq!(None, c.cache_remove(&2));
539        assert_eq!(1, c.cache_size());
540
541        assert_eq!(Some(300), c.cache_remove(&3));
542        assert_eq!(0, c.cache_size());
543    }
544
545    #[test]
546    fn remove_expired() {
547        let mut c = TimedSizedCache::with_size_and_lifespan(3, 1);
548
549        assert_eq!(c.cache_set(1, 100), None);
550        assert_eq!(c.cache_set(1, 200), Some(100));
551        assert_eq!(c.cache_size(), 1);
552
553        std::thread::sleep(std::time::Duration::from_secs(1));
554        assert_eq!(None, c.cache_remove(&1));
555        assert_eq!(0, c.cache_size());
556    }
557
558    #[test]
559    fn insert_expired() {
560        let mut c = TimedSizedCache::with_size_and_lifespan(3, 1);
561
562        assert_eq!(c.cache_set(1, 100), None);
563        assert_eq!(c.cache_set(1, 200), Some(100));
564        assert_eq!(c.cache_size(), 1);
565
566        std::thread::sleep(std::time::Duration::from_secs(1));
567        assert_eq!(1, c.cache_size());
568        assert_eq!(None, c.cache_set(1, 300));
569        assert_eq!(1, c.cache_size());
570    }
571
572    #[test]
573    fn get_expired() {
574        let mut c = TimedSizedCache::with_size_and_lifespan(3, 1);
575
576        assert_eq!(c.cache_set(1, 100), None);
577        assert_eq!(c.cache_set(1, 200), Some(100));
578        assert_eq!(c.cache_size(), 1);
579
580        std::thread::sleep(std::time::Duration::from_secs(1));
581        // still around until we try to get
582        assert_eq!(1, c.cache_size());
583        assert_eq!(None, c.cache_get(&1));
584        assert_eq!(0, c.cache_size());
585    }
586
587    #[test]
588    fn get_mut_expired() {
589        let mut c = TimedSizedCache::with_size_and_lifespan(3, 1);
590
591        assert_eq!(c.cache_set(1, 100), None);
592        assert_eq!(c.cache_set(1, 200), Some(100));
593        assert_eq!(c.cache_size(), 1);
594
595        std::thread::sleep(std::time::Duration::from_secs(1));
596        // still around until we try to get
597        assert_eq!(1, c.cache_size());
598        assert_eq!(None, c.cache_get_mut(&1));
599        assert_eq!(0, c.cache_size());
600    }
601
602    #[test]
603    fn flush_expired() {
604        let mut c = TimedSizedCache::with_size_and_lifespan(3, 1);
605
606        assert_eq!(c.cache_set(1, 100), None);
607        assert_eq!(c.cache_set(1, 200), Some(100));
608        assert_eq!(c.cache_size(), 1);
609
610        std::thread::sleep(std::time::Duration::from_secs(2));
611        // still around until we flush
612        assert_eq!(1, c.cache_size());
613        c.flush();
614        assert_eq!(0, c.cache_size());
615    }
616
617    #[test]
618    fn get_or_set_with() {
619        let mut c = TimedSizedCache::with_size_and_lifespan(5, 2);
620
621        assert_eq!(c.cache_get_or_set_with(0, || 0), &0);
622        assert_eq!(c.cache_get_or_set_with(1, || 1), &1);
623        assert_eq!(c.cache_get_or_set_with(2, || 2), &2);
624        assert_eq!(c.cache_get_or_set_with(3, || 3), &3);
625        assert_eq!(c.cache_get_or_set_with(4, || 4), &4);
626        assert_eq!(c.cache_get_or_set_with(5, || 5), &5);
627
628        assert_eq!(c.cache_misses(), Some(6));
629
630        assert_eq!(c.cache_get_or_set_with(0, || 0), &0);
631
632        assert_eq!(c.cache_misses(), Some(7));
633
634        assert_eq!(c.cache_get_or_set_with(0, || 42), &0);
635
636        sleep(Duration::new(1, 0));
637
638        assert_eq!(c.cache_get_or_set_with(0, || 42), &0);
639
640        assert_eq!(c.cache_get_or_set_with(1, || 1), &1);
641
642        assert_eq!(c.cache_get_or_set_with(4, || 42), &4);
643
644        assert_eq!(c.cache_get_or_set_with(5, || 42), &5);
645
646        assert_eq!(c.cache_get_or_set_with(6, || 6), &6);
647
648        assert_eq!(c.cache_misses(), Some(9));
649
650        sleep(Duration::new(1, 0));
651
652        assert_eq!(c.cache_get_or_set_with(4, || 42), &42);
653
654        assert_eq!(c.cache_get_or_set_with(5, || 42), &42);
655
656        assert_eq!(c.cache_get_or_set_with(6, || 42), &6);
657
658        assert_eq!(c.cache_misses(), Some(11));
659
660        c.cache_reset();
661        fn _try_get(n: usize) -> Result<usize, String> {
662            if n < 10 {
663                Ok(n)
664            } else {
665                Err("dead".to_string())
666            }
667        }
668
669        let res: Result<&mut usize, String> = c.cache_try_get_or_set_with(0, || _try_get(10));
670        assert!(res.is_err());
671        assert!(c.key_order().next().is_none());
672
673        let res: Result<&mut usize, String> = c.cache_try_get_or_set_with(0, || _try_get(1));
674        assert_eq!(res.unwrap(), &1);
675        let res: Result<&mut usize, String> = c.cache_try_get_or_set_with(0, || _try_get(5));
676        assert_eq!(res.unwrap(), &1);
677        sleep(Duration::new(2, 0));
678        let res: Result<&mut usize, String> = c.cache_try_get_or_set_with(0, || _try_get(5));
679        assert_eq!(res.unwrap(), &5);
680    }
681
682    #[cfg(feature = "async")]
683    #[tokio::test]
684    async fn test_async_trait_timed_sized() {
685        use crate::CachedAsync;
686        let mut c = TimedSizedCache::with_size_and_lifespan(5, 1);
687
688        async fn _get(n: usize) -> usize {
689            n
690        }
691
692        assert_eq!(c.get_or_set_with(0, || async { _get(0).await }).await, &0);
693        assert_eq!(c.get_or_set_with(1, || async { _get(1).await }).await, &1);
694        assert_eq!(c.get_or_set_with(2, || async { _get(2).await }).await, &2);
695        assert_eq!(c.get_or_set_with(3, || async { _get(3).await }).await, &3);
696
697        assert_eq!(c.get_or_set_with(0, || async { _get(3).await }).await, &0);
698        assert_eq!(c.get_or_set_with(1, || async { _get(3).await }).await, &1);
699        assert_eq!(c.get_or_set_with(2, || async { _get(3).await }).await, &2);
700        assert_eq!(c.get_or_set_with(3, || async { _get(1).await }).await, &3);
701
702        sleep(Duration::new(1, 0));
703        // after sleeping, the original val should have expired
704        assert_eq!(c.get_or_set_with(0, || async { _get(3).await }).await, &3);
705
706        c.cache_reset();
707        async fn _try_get(n: usize) -> Result<usize, String> {
708            if n < 10 {
709                Ok(n)
710            } else {
711                Err("dead".to_string())
712            }
713        }
714
715        assert_eq!(
716            c.try_get_or_set_with(0, || async {
717                match _try_get(0).await {
718                    Ok(n) => Ok(n),
719                    Err(_) => Err("err".to_string()),
720                }
721            })
722            .await
723            .unwrap(),
724            &0
725        );
726        assert_eq!(
727            c.try_get_or_set_with(0, || async {
728                match _try_get(5).await {
729                    Ok(n) => Ok(n),
730                    Err(_) => Err("err".to_string()),
731                }
732            })
733            .await
734            .unwrap(),
735            &0
736        );
737
738        c.cache_reset();
739        let res: Result<&mut usize, String> = c
740            .try_get_or_set_with(0, || async { _try_get(10).await })
741            .await;
742        assert!(res.is_err());
743        assert!(c.key_order().next().is_none());
744
745        let res: Result<&mut usize, String> = c
746            .try_get_or_set_with(0, || async { _try_get(1).await })
747            .await;
748        assert_eq!(res.unwrap(), &1);
749        let res: Result<&mut usize, String> = c
750            .try_get_or_set_with(0, || async { _try_get(5).await })
751            .await;
752        assert_eq!(res.unwrap(), &1);
753        sleep(Duration::new(1, 0));
754        let res: Result<&mut usize, String> = c
755            .try_get_or_set_with(0, || async { _try_get(5).await })
756            .await;
757        assert_eq!(res.unwrap(), &5);
758    }
759}