moka_cache/
lib.rs

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