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 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
135pub fn check_exp_interval() {
137 if let Some(cache) = CacheHand.get() {
138 cache.run_pending_tasks();
139 }
140}
141
142pub 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 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 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 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 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 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 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 }
330
331 fn test_cache_delete() {
333 let key = "key_u64";
334 println!("sleep 3s");
337 sleep(Duration::from_secs(3));
338 println!("get_exp:{:?}", get_exp(key));
339 println!("update:");
342 remove(key);
343 sleep(Duration::from_secs(1));
344
345 println!("get_exp:{:?}", get_exp(key));
352 }
354
355 fn test_cache_refresh() {
357 let key = "key_u64";
358 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!("del:");
369 remove(key);
370
371 println!("get_exp:{:?}", get_exp(key));
373 println!("sleep 3s");
376 sleep(Duration::from_secs(2));
377 println!("get_exp:{:?}", get_exp(key));
378 println!("sleep 5s");
381 sleep(Duration::from_secs(2));
382 println!("get_exp:{:?}", get_exp(key));
383 }
385
386 fn test_cache_refresh2() {
388 let key = "key_u64";
389 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 }
402}