mem_cache/cache/
mod.rs

1mod cache_item;
2
3use std::marker::PhantomData;
4use std::collections::HashMap;
5
6use cache_item::CacheItem;
7
8pub struct Cache<T> {
9    cache_item_map: HashMap<String, CacheItem<T>>,
10    _mark: PhantomData<T>,
11}
12
13impl<T> Cache<T> {
14    pub fn new() -> Self {
15        Self {
16            cache_item_map: HashMap::new(),
17            _mark: PhantomData,
18        }
19    }
20    pub fn fetch(&mut self, key: &str, expires_in_secs: u64, calculation: impl Fn() -> T + 'static) -> &T {
21        if self.cache_item_map.get(key).is_none() {
22            let cache_item: CacheItem<T> = CacheItem::new(expires_in_secs, calculation);
23            self.cache_item_map.insert(key.to_string(), cache_item);
24            let in_cache_item = self.cache_item_map.get_mut(key).unwrap();
25            return in_cache_item.value()
26        } else {
27            let in_cache_item = self.cache_item_map.get_mut(key).unwrap();
28            if in_cache_item.is_value_expired() {
29                let cache_item: CacheItem<T> = CacheItem::new(expires_in_secs, calculation);
30                *in_cache_item = cache_item
31            }
32            return in_cache_item.value()
33        }
34    }
35    pub fn force_fetch(&mut self, key: &str, expires_in_secs: u64, calculation: impl Fn() -> T + 'static) -> &T {
36        let cache: CacheItem<T> = CacheItem::new(expires_in_secs, calculation);
37        self.cache_item_map.insert(key.to_string(), cache);
38        self.cache_item_map.get_mut(key).unwrap().value()
39    }
40    pub fn get(&mut self, key: &str) -> anyhow::Result<&T> {
41        match self.cache_item_map.get_mut(key) {
42            Some(cache_item) => {
43                Ok(cache_item.value())
44            },
45            None => Err(anyhow::anyhow!("cache not exists"))
46        }
47    }
48    pub fn insert(&mut self, key: &str, value: T) -> anyhow::Result<()> {
49        match self.cache_item_map.get_mut(key) {
50            Some(cache_item) => {
51                cache_item.update_value(value);
52                Ok(())
53            },
54            None => Err(anyhow::anyhow!("cache not exists"))
55        }
56    }
57    pub fn expire(&mut self, key: &str) -> anyhow::Result<()> {
58        match self.cache_item_map.get_mut(key) {
59            Some(cache_item) => {
60                cache_item.expire_value();
61                Ok(())
62            },
63            None => Err(anyhow::anyhow!("cache not exists"))
64        }
65    }
66    pub fn contains_key(&self, key: &str) -> bool {
67        self.cache_item_map.contains_key(key)
68    }
69    pub fn remove(&mut self, key: &str) -> Option<CacheItem<T>> {
70        self.cache_item_map.remove(key)
71    }
72    pub fn keys(&self) -> Vec<&String> {
73        self.cache_item_map.keys().collect()
74    }
75    pub fn clear_expired(&mut self) {
76        let keys = self.keys().iter().map(|i| i.to_string()).collect::<Vec<String>>();
77        for key in keys.iter() {
78            if let Some(cache_item) = self.cache_item_map.get_mut(key) {
79                if cache_item.is_value_expired() {
80                    self.remove(key);
81                }
82            }
83        }
84    }
85    pub fn clear(&mut self) {
86        self.cache_item_map.clear();
87    }
88}
89
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94    use std::{thread, time};
95
96    #[test]
97    fn test_fetch() {
98        let mut i32_cache = Cache::<i32>::new();
99        {
100            let a =  0;
101            let v1 = i32_cache.fetch("v1", 10, move || 1 + a);
102            assert_eq!(v1, &1);
103        }
104        {
105            let v2 = i32_cache.fetch("v2", 10, || 2);
106            assert_eq!(v2, &2);
107        }
108        // again
109        {
110            let v1 = i32_cache.fetch("v1", 10, || 11);
111            assert_eq!(v1, &1);
112        }
113        {
114            let v2 = i32_cache.fetch("v2", 10, || 22);
115            assert_eq!(v2, &2);
116        }
117        //  expires
118        {
119            let v1 = i32_cache.fetch("v1_expires", 3, || 1);
120            assert_eq!(v1, &1);
121            let v1 = i32_cache.fetch("v1_expires", 0, || 2);
122            assert_eq!(v1, &1); // 数据未过期,继续使用旧数据
123            let three_secs = time::Duration::from_secs(3);
124            thread::sleep(three_secs);
125            let v1 = i32_cache.fetch("v1_expires", 0, || 3); // 0 立即失效
126            assert_eq!(v1, &3);
127            let v1 = i32_cache.fetch("v1_expires", 0, || 4);
128            assert_eq!(v1, &4);
129        }
130        let mut string_cache = Cache::<String>::new();
131        {
132            let v1 = string_cache.fetch("v1", 10, || "1".to_string());
133            assert_eq!(v1, "1");
134        }
135        {
136            let v2 = string_cache.fetch("v2", 10, || "2".to_string());
137            assert_eq!(v2, "2");
138        }
139        // again
140        {
141            let v1 = string_cache.fetch("v1", 10, || "11".to_string());
142            assert_eq!(v1, "1");
143        }
144        {
145            let v2 = string_cache.fetch("v2", 10, || "22".to_string());
146            assert_eq!(v2, "2");
147        }
148    }
149
150    #[test]
151    fn test_force_fetch() {
152        let mut i32_cache = Cache::<i32>::new();
153        let a =  0;
154        let v1 = i32_cache.force_fetch("v1", 10, move || 1 + a);
155        assert_eq!(v1, &1);
156        let v1 = i32_cache.fetch("v1", 10, move || 3 + a);
157        assert_eq!(v1, &1);
158        let v1 = i32_cache.force_fetch("v1", 10, move || 2 + a);
159        assert_eq!(v1, &2);
160        let v1 = i32_cache.fetch("v1", 10, move || 3 + a);
161        assert_eq!(v1, &2);
162    }
163
164    #[test]
165    fn test_get() {
166        let mut i32_cache = Cache::<i32>::new();
167        let a =  0;
168        let v1 = i32_cache.force_fetch("v1", 10, move || 1 + a);
169        assert_eq!(v1, &1);
170        let v1 = i32_cache.get("v1");
171        assert_eq!(v1.unwrap(), &1);
172        let v1 = i32_cache.get("v2");
173        assert!(v1.is_err());
174    }
175
176    #[test]
177    fn test_insert() {
178        let mut i32_cache = Cache::<i32>::new();
179        let a =  0;
180        let v1 = i32_cache.fetch("v1", 10, move || 1 + a);
181        assert_eq!(v1, &1);
182        i32_cache.insert("v1", 2).unwrap();
183        let v1 = i32_cache.fetch("v1", 10, move || 1 + a);
184        assert_eq!(v1, &2);
185    }
186
187    #[test]
188    fn test_expire() {
189        let mut i32_cache = Cache::<i32>::new();
190        let a =  0;
191        let v1 = i32_cache.fetch("v1", 10, move || 1 + a);
192        assert_eq!(v1, &1);
193        i32_cache.expire("v1").unwrap();
194        let v1 = i32_cache.fetch("v1", 10, move || 2 + a);
195        assert_eq!(v1, &2);
196    }
197
198    #[test]
199    fn test_remove() {
200        let mut i32_cache = Cache::<i32>::new();
201        let a =  0;
202        let v1 = i32_cache.force_fetch("v1", 10, move || 1 + a);
203        assert_eq!(v1, &1);
204        let v1 = i32_cache.remove("v1");
205        assert!(v1.is_some());
206    }
207
208    #[test]
209    fn test_others() {
210        // contains_key
211        let mut i32_cache = Cache::<i32>::new();
212        assert_eq!(i32_cache.contains_key("v1"), false);
213        i32_cache.force_fetch("v1", 10, move || 1);
214        i32_cache.force_fetch("v2", 0, move || 2);
215        assert_eq!(i32_cache.contains_key("v1"), true);
216        // keys
217        let mut keys = i32_cache.keys();
218        keys.sort();
219        assert_eq!(keys, vec!["v1", "v2"]);
220        // clear_expired
221        i32_cache.clear_expired();
222        assert_eq!(i32_cache.keys(), vec!["v1"]);
223        // clear
224        i32_cache.clear();
225        assert!(i32_cache.keys().is_empty());
226    }
227}