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
54pub 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
138pub fn check_exp_interval() {
140 if let Some(cache) = CacheHand.get() {
141 cache.run_pending_tasks();
142 }
143}
144
145pub 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 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 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 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 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 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 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 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 }
347
348 fn test_cache_delete() {
350 let key = "key_u64";
351 println!("sleep 3s");
354 sleep(Duration::from_secs(3));
355 println!("get_exp:{:?}", get_exp(key));
356 println!("update:");
359 remove(key);
360 sleep(Duration::from_secs(1));
361
362 println!("get_exp:{:?}", get_exp(key));
369 }
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}