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 v = h.get(&key.into())?;
92        let c = config::standard();
93        let b = bincode::decode_from_slice::<V, _>(v.1.as_ref(), c);
94        if let Ok((value, _)) = b {
95            return Some((v.0, value));
96        }
97        if let Err(e) = b {
98            log::error!("cache deserialize error: {}", e.to_string());
99        }
100        return None;
101    }
102
103    None
104}
105
106pub fn get_exp<K>(key: K) -> Option<Expiration>
107where
108    K: Into<String>,
109{
110    let value = CacheHand.get().map(|h| h.get(&key.into())).unwrap_or(None);
111    if let Some(v) = value {
112        return Some(v.0);
113    }
114    None
115}
116
117pub fn remove<K>(key: K)
118where
119    K: Into<String>,
120{
121    let k = key.into();
122    CacheHand.get().map(|h| {
123        h.invalidate(&k);
124    });
125}
126
127pub fn contains_key<K>(key: K) -> bool
128where
129    K: Into<String>,
130{
131    let k = key.into();
132    CacheHand.get().map(|h| h.contains_key(&k)).unwrap_or(false)
133}
134
135//每隔10检查缓存是否过期
136pub fn check_exp_interval() {
137    if let Some(cache) = CacheHand.get() {
138        cache.run_pending_tasks();
139    }
140}
141
142// 刷新key ttl
143pub fn refresh<K>(key: K) -> Result<()>
144where
145    K: Into<String>,
146{
147    let k = key.into();
148    let value = get(&k);
149
150    let Some(value) = value else {
151        return Err(anyhow!("key: {} not found", k));
152    };
153
154    if value.0 == Expiration::Never {
155        return Ok(());
156    }
157
158    remove(&k);
159
160    if let Some(c) = CacheHand.get() {
161        c.insert(k, value);
162    }
163
164    Ok(())
165}
166
167#[cfg(test)]
168#[allow(dead_code)]
169mod test {
170
171    use super::*;
172    use std::thread::sleep;
173
174    fn cache_key_expired(_key: Arc<String>, _: CacheData, _case: RemovalCause) {}
175    fn init() {
176        setup(Some(cache_key_expired), 512).unwrap();
177    }
178
179    #[test]
180    fn test_encode_decode() {
181        let value: i32 = 1000;
182        let config = config::standard().with_little_endian();
183        let b = bincode::encode_to_vec(&value, config).unwrap();
184        println!("b-->{:?}", b);
185        let (value, _) = bincode::decode_from_slice::<i32, _>(b.as_ref(), config).unwrap();
186        println!("value-->{}", value);
187    }
188
189    #[test]
190    fn test_cache_u16() {
191        init();
192        remove("test_cache_get_u1622");
193        insert("test_cache_get_u1622", 1000, Expiration::Never).unwrap();
194        let v = get::<_, u32>("test_cache_get_u1622");
195        println!("test_cache_get_u1622-->{:?}", v);
196    }
197
198    #[test]
199    fn test_cache_byte() {
200        init();
201        let b = b"hello world".to_vec();
202        insert("test_cache_get_byte", b, Expiration::Never).unwrap();
203        let v = get::<_, Vec<u8>>("test_cache_get_byte");
204        println!("test_cache_get_byte-->{:?}", v);
205    }
206
207    #[test]
208    fn test_cache_struct() {
209        #[derive(Encode, Decode, Debug, Clone, Serialize, Deserialize)]
210        struct Config {
211            pub path: String,
212            pub cache_capacity: u32,
213            pub len: usize,
214        }
215        init();
216        let b = Config {
217            path: "test".to_string(),
218            cache_capacity: 1024,
219            len: 1024,
220        };
221        insert("test_cache_struct", b, Expiration::Never).unwrap();
222        let v = get::<_, Config>("test_cache_struct");
223        println!("test_cache_struct-->{:?}", v);
224    }
225
226    #[test]
227    fn test_cache_get() {
228        init();
229
230        //
231        insert("test_cache_get", "hello world", Expiration::Never).unwrap();
232        let v = get::<_, String>("test_cache_get");
233        println!("test_cache_get--->: {:?}", v);
234
235        //
236        insert("test_cache_get_bool", true, Expiration::Never).unwrap();
237        let v = get::<_, bool>("test_cache_get_bool");
238        println!("test_cache_get_bool-->{:?}", v);
239
240        insert("test_cache_get_bool_false", false, Expiration::Never).unwrap();
241        let v = get::<_, bool>("test_cache_get_bool_false");
242        println!("test_cache_get_bool_false-->{:?}", v);
243
244        //
245        insert("test_cache_get_i32", 1000, Expiration::Never).unwrap();
246        let v = get::<_, i32>("test_cache_get_i32");
247        println!("test_cache_get_i32-->{:?}", v);
248
249        //
250        insert(
251            "test_cache_get_byte",
252            b"hello world".to_vec(),
253            Expiration::Never,
254        )
255        .unwrap();
256        let v = get::<_, Vec<u8>>("test_cache_get_byte");
257        println!("test_cache_get_byte-->{:?}", v);
258    }
259
260    //
261    fn test_src_mcache() {
262        let expiry = CacheExpiry;
263
264        let eviction_listener = |key, value, cause| {
265            println!("过期 key-----> {key}. value--> {value:?}. Cause: {cause:?}");
266        };
267
268        let cache = Cache::builder()
269            .max_capacity(100)
270            .expire_after(expiry)
271            .eviction_listener(eviction_listener)
272            .build();
273
274        cache.insert("0".to_string(), (Expiration::Second(5), b"a".to_vec()));
275        cache.insert("1".to_string(), (Expiration::Second(6), b"b".to_vec()));
276        cache.insert("2".to_string(), (Expiration::Never, b"c".to_vec()));
277        cache.insert("3".to_string(), (Expiration::Never, b"3333".to_vec()));
278        //update
279        cache.insert(
280            "0".to_string(),
281            (Expiration::Second(10), b"abbbbaa".to_vec()),
282        );
283
284        println!("Entry count: {}", cache.entry_count());
285
286        let Some(v) = cache.get("0") else {
287            println!("cache.get(&0): none");
288            return;
289        };
290        println!("cache.get(&0): {:?}", v);
291
292        println!("0 {}", cache.contains_key("0"));
293        println!("1 {}", cache.contains_key("1"));
294        println!("2 {}", cache.contains_key("2"));
295        println!("3 {}", cache.contains_key("3"));
296
297        let re = cache.remove("3");
298        println!("remove:{:?}", re);
299
300        println!("\n Sleeping for 6 seconds...\n");
301        sleep(Duration::from_secs(6));
302
303        println!("Entry count: {}", cache.entry_count());
304        println!("0 {}", cache.contains_key("0"));
305        println!("1 {}", cache.contains_key("1"));
306        println!("2 {}", cache.contains_key("2"));
307        println!("3 {}", cache.contains_key("3"));
308
309        let Some(v) = cache.get("2") else {
310            return;
311        };
312        println!("cache.get(2): {:?}", v);
313        sleep(Duration::from_secs(6));
314    }
315
316    fn test_cache_evication() {
317        let _ = check_exp_interval();
318        insert("check_evication", "过期了value", Expiration::Second(5)).unwrap();
319        sleep(Duration::from_secs(3));
320        println!("sleep 3s");
321
322        let (_, v) = get::<_, String>("check_evication").unwrap();
323        println!("get_string:{:?}", v);
324        println!("sleep 3s");
325        sleep(Duration::from_secs(3));
326        println!("contains_key:{:?}", contains_key("check_evication"));
327        sleep(Duration::from_secs(3));
328        //println!("get_string:{:?}", get_string("check_evication"));
329    }
330
331    //
332    fn test_cache_delete() {
333        let key = "key_u64";
334        // insert_u64("key_u64", 555, Expiration::Second(6));
335
336        println!("sleep 3s");
337        sleep(Duration::from_secs(3));
338        println!("get_exp:{:?}", get_exp(key));
339        //   println!("get_u64:{:?}", get_u64(&key));
340
341        println!("update:");
342        remove(key);
343        sleep(Duration::from_secs(1));
344
345        // insert_u64(key.to_string(), 666, Expiration::Second(12));
346        // println!("get_exp:{:?}", get_exp(&key));
347        // println!("get_u64:{:?}", get_u64(&key));
348
349        // println!("sleep 3s");
350        // sleep(Duration::from_secs(3));
351        println!("get_exp:{:?}", get_exp(key));
352        // println!("get_u64:{:?}", get_u64(&key));
353    }
354
355    //
356    fn test_cache_refresh() {
357        let key = "key_u64";
358        //insert_u64("key_u64", 555, Expiration::Second(6));
359
360        println!("sleep 3s");
361        sleep(Duration::from_secs(3));
362        let Some(exp_at) = get_exp(key) else {
363            return;
364        };
365        println!("get_exp:{:?}", exp_at);
366        //   println!("get_u64:{:?}", get_u64(&key));
367
368        println!("del:");
369        remove(key);
370
371        // insert_u64(key, 666, exp_at);
372        println!("get_exp:{:?}", get_exp(key));
373        // println!("get_u64:{:?}", get_u64(&key));
374
375        println!("sleep 3s");
376        sleep(Duration::from_secs(2));
377        println!("get_exp:{:?}", get_exp(key));
378        //println!("get_u64:{:?}", get_u64(&key));
379
380        println!("sleep 5s");
381        sleep(Duration::from_secs(2));
382        println!("get_exp:{:?}", get_exp(key));
383        //  println!("get_u64:{:?}", get_u64(&key));
384    }
385
386    //
387    fn test_cache_refresh2() {
388        let key = "key_u64";
389        //insert_u64(key, 555, Expiration::Second(4));
390
391        println!("sleep 2s");
392        sleep(Duration::from_secs(2));
393
394        println!("refresh: ");
395        refresh(key).expect("refresh error");
396
397        println!("sleep 5s");
398        sleep(Duration::from_secs(5));
399        println!("get_exp:{:?}", get_exp(key));
400        //  println!("get_u64:{:?}", get_u64(&key));
401    }
402}