moka_cache/
lib.rs

1#![allow(non_upper_case_globals)]
2use anyhow::{anyhow, Result};
3use bincode::config;
4pub use bincode::{Decode, Encode};
5pub use moka::notification::RemovalCause;
6use moka::{sync::Cache, Expiry};
7#[allow(unused_imports)]
8use serde::{de::DeserializeOwned, Deserialize, Serialize};
9use std::{
10    sync::Arc,
11    sync::OnceLock,
12    time::{Duration, Instant},
13};
14
15#[derive(Clone, Copy, Debug, Eq, PartialEq)]
16pub enum Expiration {
17    Never,
18    Second(u64),
19    Minute(u64),
20    Hour(u64),
21}
22
23impl Expiration {
24    pub fn as_duration(&self) -> Option<Duration> {
25        match self {
26            Expiration::Never => None,
27            Expiration::Second(v) => Some(Duration::from_secs(*v)),
28            Expiration::Minute(v) => Some(Duration::from_secs(*v * 60)),
29            Expiration::Hour(v) => Some(Duration::from_secs(*v * 60 * 60)),
30        }
31    }
32}
33
34pub struct CacheExpiry;
35
36pub type CacheData = (Expiration, Vec<u8>);
37
38type AppCache = Cache<String, (Expiration, Vec<u8>)>;
39
40impl Expiry<String, (Expiration, Vec<u8>)> for CacheExpiry {
41    #[allow(unused_variables)]
42    fn expire_after_create(
43        &self,
44        key: &String,
45        value: &(Expiration, Vec<u8>),
46        current_time: Instant,
47    ) -> Option<Duration> {
48        value.0.as_duration()
49    }
50}
51
52static CacheHand: OnceLock<AppCache> = OnceLock::new();
53
54//初始化缓存
55pub fn setup(
56    callback: Option<fn(Arc<String>, CacheData, RemovalCause)>,
57    max_cap: u64,
58) -> Result<()> {
59    let mut c = Cache::builder()
60        .max_capacity(max_cap)
61        .expire_after(CacheExpiry {});
62
63    if let Some(callback) = callback {
64        c = c.eviction_listener(callback);
65    }
66    let c = c.build();
67    CacheHand
68        .set(c)
69        .map_err(|e| anyhow!("setup cache error:{:?}", e))?;
70    Ok(())
71}
72
73pub fn insert<K, V>(key: K, value: V, exp: Expiration) -> Result<()>
74where
75    K: Into<String>,
76    V: Serialize + Encode + Sync + Send,
77{
78    let cache = CacheHand.get().ok_or_else(|| anyhow!("cache is null"))?;
79    let k = key.into();
80    let b = bincode::encode_to_vec(&value, config::standard())?;
81    cache.insert(k, (exp, b));
82    Ok(())
83}
84
85pub fn get<K, V>(key: K) -> Option<(Expiration, V)>
86where
87    K: Into<String>,
88    V: DeserializeOwned + Decode<()> + Sync + Send,
89{
90    if let Some(h) = CacheHand.get() {
91        let k = key.into();
92
93        let v = h.get(&k)?;
94
95        let c = config::standard();
96        let b = bincode::decode_from_slice::<V, _>(v.1.as_ref(), c);
97        if let Ok((value, _)) = b {
98            return Some((v.0, value));
99        }
100        if let Err(e) = b {
101            log::error!("cache deserialize error: {}", e.to_string());
102        }
103        return None;
104    }
105
106    None
107}
108
109pub fn get_exp<K>(key: K) -> Option<Expiration>
110where
111    K: Into<String>,
112{
113    let value = CacheHand.get().map(|h| h.get(&key.into())).unwrap_or(None);
114    if let Some(v) = value {
115        return Some(v.0);
116    }
117    None
118}
119
120pub fn remove<K>(key: K)
121where
122    K: Into<String>,
123{
124    let k = key.into();
125    CacheHand.get().map(|h| {
126        h.invalidate(&k);
127    });
128}
129
130pub fn contains_key<K>(key: K) -> bool
131where
132    K: Into<String>,
133{
134    let k = key.into();
135    CacheHand.get().map(|h| h.contains_key(&k)).unwrap_or(false)
136}
137
138//每隔10检查缓存是否过期
139pub fn check_exp_interval() {
140    if let Some(cache) = CacheHand.get() {
141        cache.run_pending_tasks();
142    }
143}
144
145// 刷新key ttl
146pub fn refresh<K>(key: K) -> Result<()>
147where
148    K: Into<String>,
149{
150    if let Some(h) = CacheHand.get() {
151        let k = key.into();
152        let v = h.get(&k);
153        let Some(v) = v else {
154            return Err(anyhow!("key: {} not found", k));
155        };
156
157        if v.0 == Expiration::Never {
158            return Ok(());
159        }
160
161        h.invalidate(&k);
162
163        h.insert(k, v);
164
165        return Ok(());
166    }
167
168    Err(anyhow!("cache is null"))
169}
170
171#[cfg(test)]
172#[allow(dead_code)]
173mod test {
174
175    use super::*;
176    use std::thread::sleep;
177
178    fn cache_key_expired(_key: Arc<String>, _: CacheData, _case: RemovalCause) {}
179    fn init() {
180        setup(Some(cache_key_expired), 512).unwrap();
181    }
182
183    #[test]
184    fn test_encode_decode() {
185        let value: i32 = 1000;
186        let config = config::standard().with_little_endian();
187        let b = bincode::encode_to_vec(&value, config).unwrap();
188        println!("b-->{:?}", b);
189        let (value, _) = bincode::decode_from_slice::<i32, _>(b.as_ref(), config).unwrap();
190        println!("value-->{}", value);
191    }
192
193    #[test]
194    fn test_cache_u16() {
195        init();
196        remove("test_cache_get_u1622");
197        insert("test_cache_get_u1622", 1000, Expiration::Never).unwrap();
198        let v = get::<_, u32>("test_cache_get_u1622");
199        println!("test_cache_get_u1622-->{:?}", v);
200    }
201
202    #[test]
203    fn test_cache_byte() {
204        init();
205        let b = b"hello world".to_vec();
206        insert("test_cache_get_byte", b, Expiration::Never).unwrap();
207        let v = get::<_, Vec<u8>>("test_cache_get_byte");
208        println!("test_cache_get_byte-->{:?}", v);
209    }
210
211    #[test]
212    fn test_cache_struct() {
213        #[derive(Encode, Decode, Debug, Clone, Serialize, Deserialize)]
214        struct Config {
215            pub path: String,
216            pub cache_capacity: u32,
217            pub len: usize,
218        }
219        init();
220        let b = Config {
221            path: "test".to_string(),
222            cache_capacity: 1024,
223            len: 1024,
224        };
225        insert("test_cache_struct", b, Expiration::Never).unwrap();
226        let v = get::<_, Config>("test_cache_struct");
227        println!("test_cache_struct-->{:?}", v);
228    }
229
230    #[test]
231    fn test_cache_get() {
232        init();
233
234        //
235        insert("test_cache_get", "hello world", Expiration::Never).unwrap();
236        let v = get::<_, String>("test_cache_get");
237        println!("test_cache_get--->: {:?}", v);
238
239        //
240        insert("test_cache_get_bool", true, Expiration::Never).unwrap();
241        let v = get::<_, bool>("test_cache_get_bool");
242        println!("test_cache_get_bool-->{:?}", v);
243
244        insert("test_cache_get_bool_false", false, Expiration::Never).unwrap();
245        let v = get::<_, bool>("test_cache_get_bool_false");
246        println!("test_cache_get_bool_false-->{:?}", v);
247
248        //
249        insert("test_cache_get_i32", 1000, Expiration::Never).unwrap();
250        let v = get::<_, i32>("test_cache_get_i32");
251        println!("test_cache_get_i32-->{:?}", v);
252
253        //
254        insert(
255            "test_cache_get_byte",
256            b"hello world".to_vec(),
257            Expiration::Never,
258        )
259        .unwrap();
260        let v = get::<_, Vec<u8>>("test_cache_get_byte");
261        println!("test_cache_get_byte-->{:?}", v);
262    }
263
264    #[test]
265    fn test_cache_get2() {
266        init();
267
268        let key: String = "test_cache_get2".into();
269        //
270        insert(&key, 55, Expiration::Never).unwrap();
271        let v = get::<_, i32>("test_cache_get2");
272        println!("test_cache_get2 str--->: {:?}", v);
273
274        let v = get::<_, i32>(key);
275        println!("test_cache_get2 string--->: {:?}", v);
276    }
277    //
278    fn test_src_mcache() {
279        let expiry = CacheExpiry;
280
281        let eviction_listener = |key, value, cause| {
282            println!("过期 key-----> {key}. value--> {value:?}. Cause: {cause:?}");
283        };
284
285        let cache = Cache::builder()
286            .max_capacity(100)
287            .expire_after(expiry)
288            .eviction_listener(eviction_listener)
289            .build();
290
291        cache.insert("0".to_string(), (Expiration::Second(5), b"a".to_vec()));
292        cache.insert("1".to_string(), (Expiration::Second(6), b"b".to_vec()));
293        cache.insert("2".to_string(), (Expiration::Never, b"c".to_vec()));
294        cache.insert("3".to_string(), (Expiration::Never, b"3333".to_vec()));
295        //update
296        cache.insert(
297            "0".to_string(),
298            (Expiration::Second(10), b"abbbbaa".to_vec()),
299        );
300
301        println!("Entry count: {}", cache.entry_count());
302
303        let Some(v) = cache.get("0") else {
304            println!("cache.get(&0): none");
305            return;
306        };
307        println!("cache.get(&0): {:?}", v);
308
309        println!("0 {}", cache.contains_key("0"));
310        println!("1 {}", cache.contains_key("1"));
311        println!("2 {}", cache.contains_key("2"));
312        println!("3 {}", cache.contains_key("3"));
313
314        let re = cache.remove("3");
315        println!("remove:{:?}", re);
316
317        println!("\n Sleeping for 6 seconds...\n");
318        sleep(Duration::from_secs(6));
319
320        println!("Entry count: {}", cache.entry_count());
321        println!("0 {}", cache.contains_key("0"));
322        println!("1 {}", cache.contains_key("1"));
323        println!("2 {}", cache.contains_key("2"));
324        println!("3 {}", cache.contains_key("3"));
325
326        let Some(v) = cache.get("2") else {
327            return;
328        };
329        println!("cache.get(2): {:?}", v);
330        sleep(Duration::from_secs(6));
331    }
332
333    fn test_cache_evication() {
334        let _ = check_exp_interval();
335        insert("check_evication", "过期了value", Expiration::Second(5)).unwrap();
336        sleep(Duration::from_secs(3));
337        println!("sleep 3s");
338
339        let (_, v) = get::<_, String>("check_evication").unwrap();
340        println!("get_string:{:?}", v);
341        println!("sleep 3s");
342        sleep(Duration::from_secs(3));
343        println!("contains_key:{:?}", contains_key("check_evication"));
344        sleep(Duration::from_secs(3));
345        //println!("get_string:{:?}", get_string("check_evication"));
346    }
347
348    //
349    fn test_cache_delete() {
350        let key = "key_u64";
351        // insert_u64("key_u64", 555, Expiration::Second(6));
352
353        println!("sleep 3s");
354        sleep(Duration::from_secs(3));
355        println!("get_exp:{:?}", get_exp(key));
356        //   println!("get_u64:{:?}", get_u64(&key));
357
358        println!("update:");
359        remove(key);
360        sleep(Duration::from_secs(1));
361
362        // insert_u64(key.to_string(), 666, Expiration::Second(12));
363        // println!("get_exp:{:?}", get_exp(&key));
364        // println!("get_u64:{:?}", get_u64(&key));
365
366        // println!("sleep 3s");
367        // sleep(Duration::from_secs(3));
368        println!("get_exp:{:?}", get_exp(key));
369        // println!("get_u64:{:?}", get_u64(&key));
370    }
371
372    #[test]
373    fn test_cache_expire() {
374        init();
375        let key = "key_i32";
376        insert("key_i32", 555, Expiration::Second(6)).unwrap();
377
378        println!("sleep 3s");
379        sleep(Duration::from_secs(3));
380        let Some(exp_at) = get_exp(key) else {
381            return;
382        };
383        println!("get_exp:{:?}", exp_at);
384        let v = get::<_, i32>(key);
385        println!("get_i32:{:?}", v);
386
387        println!("sleep 3s");
388        sleep(Duration::from_secs(2));
389        println!("get_exp:{:?}", get_exp(key));
390
391        println!("sleep 5s");
392        sleep(Duration::from_secs(2));
393        let v = get::<_, i32>(key);
394        println!("get_i32:{:?}", v);
395    }
396
397    #[test]
398    fn test_cache_refresh() {
399        init();
400        let key = "key_i32".to_string();
401        insert(&key, 555, Expiration::Second(6)).unwrap();
402        let v = get::<_, i32>(&key);
403        println!("get_i32:{:?}", v);
404
405        sleep(Duration::from_secs(2));
406        let Some(exp_at) = get_exp(&key) else {
407            return;
408        };
409        println!("get_exp:{:?}", exp_at);
410
411        if let Err(e) = refresh(&key) {
412            println!("refresh error:{:?}", e);
413            return;
414        }
415        println!("refresh get_exp:{:?}", get_exp(&key));
416
417        println!("sleep 7s");
418        sleep(Duration::from_secs(7));
419        let v = get::<_, i32>(key);
420        println!("get_i32:{:?}", v);
421    }
422}