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
55pub 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
74pub 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
134pub 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
187pub fn check_exp_interval() {
189 if let Some(cache) = CacheHand.get() {
190 cache.run_pending_tasks();
191 }
192}
193
194pub 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 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 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 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 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 fn test_cache_delete() {
318 let key = "key_u64";
319 println!("sleep 3s");
322 sleep(Duration::from_secs(3));
323 println!("get_exp:{:?}", get_exp(key));
324 println!("update:");
327 remove(key);
328 sleep(Duration::from_secs(1));
329
330 println!("get_exp:{:?}", get_exp(key));
337 }
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}