cat_gateway/service/utilities/
cache.rs

1//! Cache wrapper type
2use std::{collections::hash_map::RandomState, hash::Hash};
3
4use get_size2::GetSize;
5use moka::{policy::EvictionPolicy, sync::Cache as BaseCache};
6
7/// Cache type that is disabled if the maximum capacity is set to zero.
8#[derive(Clone)]
9pub(crate) struct Cache<K, V> {
10    /// Optional `moka::sync::Cache`.
11    inner: Option<BaseCache<K, V, RandomState>>,
12}
13
14impl<K, V> Cache<K, V>
15where
16    K: Hash + Eq + Send + Sync + 'static,
17    V: Clone + Send + Sync + 'static,
18{
19    /// Function to determine cache entry weighted size.
20    fn weigher_fn(
21        k: &K,
22        v: &V,
23    ) -> u32 {
24        let k_size = GetSize::get_size(&k);
25        let v_size = GetSize::get_size(&v);
26        k_size.saturating_add(v_size).try_into().unwrap_or(u32::MAX)
27    }
28
29    /// Constructs a new `Cache`.
30    pub(crate) fn new(
31        name: &str,
32        eviction_policy: EvictionPolicy,
33        max_capacity: u64,
34    ) -> Self {
35        let inner = if max_capacity < 1 {
36            None
37        } else {
38            let cache = BaseCache::builder()
39                .name(name)
40                .eviction_policy(eviction_policy)
41                .max_capacity(max_capacity)
42                .weigher(Self::weigher_fn);
43            Some(cache.build())
44        };
45        Self { inner }
46    }
47
48    /// Get entry from the cache by key.
49    pub(crate) fn get(
50        &self,
51        key: &K,
52    ) -> Option<V> {
53        self.inner.as_ref().and_then(|cache| cache.get(key))
54    }
55
56    /// Insert entry into the cache.
57    pub(crate) fn insert(
58        &self,
59        key: K,
60        value: V,
61    ) {
62        self.inner
63            .as_ref()
64            .inspect(|cache| cache.insert(key, value));
65    }
66
67    /// Clear entries in the cache.
68    pub(crate) fn clear_cache(&self) {
69        self.inner.as_ref().inspect(|cache| cache.invalidate_all());
70    }
71
72    /// Weighted-size of the cache.
73    pub(crate) fn weighted_size(&self) -> u64 {
74        self.inner
75            .as_ref()
76            .inspect(|cache| {
77                cache.run_pending_tasks();
78            })
79            .map(BaseCache::weighted_size)
80            .unwrap_or_default()
81    }
82
83    /// Number of entries in the cache.
84    pub(crate) fn entry_count(&self) -> u64 {
85        self.inner
86            .as_ref()
87            .inspect(|cache| {
88                cache.run_pending_tasks();
89            })
90            .map(BaseCache::entry_count)
91            .unwrap_or_default()
92    }
93
94    /// Returns `true` if the cache is enabled.
95    pub(crate) fn is_enabled(&self) -> bool {
96        self.inner.is_some()
97    }
98}