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, Equivalent, Expiry};
7#[allow(unused_imports)]
8use serde::{de::DeserializeOwned, Deserialize, Serialize};
9use std::{
10 hash::Hash,
11 sync::Arc,
12 sync::OnceLock,
13 time::{Duration, Instant},
14};
15
16#[derive(Clone, Copy, Debug, Eq, PartialEq)]
17pub enum Expiration {
18 Never,
19 Second(u64),
20 Minute(u64),
21 Hour(u64),
22}
23
24impl Expiration {
25 pub fn as_duration(&self) -> Option<Duration> {
26 match self {
27 Expiration::Never => None,
28 Expiration::Second(v) => Some(Duration::from_secs(*v)),
29 Expiration::Minute(v) => Some(Duration::from_secs(*v * 60)),
30 Expiration::Hour(v) => Some(Duration::from_secs(*v * 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<()>
75where
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().with_little_endian())?;
82 cache.insert(k, (exp, b));
83 Ok(())
84}
85
86pub fn get<K, V>(key: &K) -> Option<(Expiration, V)>
87where
88 K: Equivalent<String> + Hash + ?Sized,
89 V: DeserializeOwned + Decode<()> + Sync + Send,
90{
91 if let Some(h) = CacheHand.get() {
92 let v = h.get(key)?;
93 let c = config::standard();
94 let b = bincode::decode_from_slice::<V, _>(v.1.as_ref(), c);
95 if let Ok((value, _)) = b {
96 return Some((v.0, value));
97 }
98 if let Err(e) = b {
99 log::error!("cache deserialize error: {}", e.to_string());
100 }
101 return None;
102 }
103
104 None
105}
106
107pub fn get_exp<K>(key: &K) -> Option<Expiration>
108where
109 K: Equivalent<String> + Hash + ?Sized,
110{
111 let value = CacheHand.get().map(|h| h.get(key)).unwrap_or(None);
112 if let Some(v) = value {
113 return Some(v.0);
114 }
115 None
116}
117
118pub fn remove<K>(key: &K)
119where
120 K: Equivalent<String> + Hash + ?Sized,
121{
122 CacheHand.get().map(|h| {
123 h.invalidate(key);
124 });
125}
126
127pub fn contains_key<K>(key: &K) -> bool
128where
129 K: Equivalent<String> + Hash + ?Sized,
130{
131 CacheHand
132 .get()
133 .map(|h| h.contains_key(key))
134 .unwrap_or(false)
135}
136
137pub fn check_exp_interval() {
139 if let Some(cache) = CacheHand.get() {
140 cache.run_pending_tasks();
141 }
142}
143
144pub fn refresh<K>(key: &K) -> Result<()>
146where
147 K: Equivalent<String> + Hash + std::fmt::Display + ?Sized,
148{
149 let value = get(key);
150
151 let Some(value) = value else {
152 return Err(anyhow!("key: {} not found", key));
153 };
154
155 if value.0 == Expiration::Never {
156 return Ok(());
157 }
158
159 remove(key);
160
161 if let Some(c) = CacheHand.get() {
162 c.insert(key.to_string(), value);
163 }
164
165 Ok(())
166}
167
168#[cfg(test)]
169#[allow(dead_code)]
170mod test {
171
172 use super::*;
173 use std::thread::sleep;
174
175 fn cache_key_expired(_key: Arc<String>, _: CacheData, _case: RemovalCause) {}
176 fn init() {
177 setup(Some(cache_key_expired), 512).unwrap();
178 }
179
180 #[test]
181 fn test_encode_decode() {
182 let value: i32 = 1000;
183 let config = config::standard().with_little_endian();
184 let b = bincode::encode_to_vec(&value, config).unwrap();
185 println!("b-->{:?}", b);
186 let (value, _) = bincode::decode_from_slice::<i32, _>(b.as_ref(), config).unwrap();
187 println!("value-->{}", value);
188 }
189
190 #[test]
191 fn test_cache_u16() {
192 init();
193 remove("test_cache_get_u1622");
194 insert("test_cache_get_u1622", 1000, Expiration::Never).unwrap();
195 let v = get::<_, u32>("test_cache_get_u1622");
196 println!("test_cache_get_u1622-->{:?}", v);
197 }
198
199 #[test]
200 fn test_cache_byte() {
201 init();
202 let b = b"hello world".to_vec();
203 insert("test_cache_get_byte", b, Expiration::Never).unwrap();
204 let v = get::<_, Vec<u8>>("test_cache_get_byte");
205 println!("test_cache_get_byte-->{:?}", v);
206 }
207
208 #[test]
209 fn test_cache_struct() {
210 #[derive(Encode, Decode, Debug, Clone, Serialize, Deserialize)]
211 struct Config {
212 pub path: String,
213 pub cache_capacity: u32,
214 pub len: usize,
215 }
216 init();
217 let b = Config {
218 path: "test".to_string(),
219 cache_capacity: 1024,
220 len: 1024,
221 };
222 insert("test_cache_struct", b, Expiration::Never).unwrap();
223 let v = get::<_, Config>("test_cache_struct");
224 println!("test_cache_struct-->{:?}", v);
225 }
226
227 #[test]
228 fn test_cache_get() {
229 init();
230
231 insert("test_cache_get", "hello world", Expiration::Never).unwrap();
233 let v = get::<_, String>("test_cache_get");
234 println!("test_cache_get--->: {:?}", v);
235
236 insert("test_cache_get_bool", true, Expiration::Never).unwrap();
238 let v = get::<_, bool>("test_cache_get_bool");
239 println!("test_cache_get_bool-->{:?}", v);
240
241 insert("test_cache_get_bool_false", false, Expiration::Never).unwrap();
242 let v = get::<_, bool>("test_cache_get_bool_false");
243 println!("test_cache_get_bool_false-->{:?}", v);
244
245 insert("test_cache_get_i32", 1000, Expiration::Never).unwrap();
247 let v = get::<_, i32>("test_cache_get_i32");
248 println!("test_cache_get_i32-->{:?}", v);
249
250 insert(
252 "test_cache_get_byte",
253 b"hello world".to_vec(),
254 Expiration::Never,
255 )
256 .unwrap();
257 let v = get::<_, Vec<u8>>("test_cache_get_byte");
258 println!("test_cache_get_byte-->{:?}", v);
259 }
260
261 fn test_src_mcache() {
263 let expiry = CacheExpiry;
264
265 let eviction_listener = |key, value, cause| {
266 println!("过期 key-----> {key}. value--> {value:?}. Cause: {cause:?}");
267 };
268
269 let cache = Cache::builder()
270 .max_capacity(100)
271 .expire_after(expiry)
272 .eviction_listener(eviction_listener)
273 .build();
274
275 cache.insert("0".to_string(), (Expiration::Second(5), b"a".to_vec()));
276 cache.insert("1".to_string(), (Expiration::Second(6), b"b".to_vec()));
277 cache.insert("2".to_string(), (Expiration::Never, b"c".to_vec()));
278 cache.insert("3".to_string(), (Expiration::Never, b"3333".to_vec()));
279 cache.insert(
281 "0".to_string(),
282 (Expiration::Second(10), b"abbbbaa".to_vec()),
283 );
284
285 println!("Entry count: {}", cache.entry_count());
286
287 let Some(v) = cache.get("0") else {
288 println!("cache.get(&0): none");
289 return;
290 };
291 println!("cache.get(&0): {:?}", v);
292
293 println!("0 {}", cache.contains_key("0"));
294 println!("1 {}", cache.contains_key("1"));
295 println!("2 {}", cache.contains_key("2"));
296 println!("3 {}", cache.contains_key("3"));
297
298 let re = cache.remove("3");
299 println!("remove:{:?}", re);
300
301 println!("\n Sleeping for 6 seconds...\n");
302 sleep(Duration::from_secs(6));
303
304 println!("Entry count: {}", cache.entry_count());
305 println!("0 {}", cache.contains_key("0"));
306 println!("1 {}", cache.contains_key("1"));
307 println!("2 {}", cache.contains_key("2"));
308 println!("3 {}", cache.contains_key("3"));
309
310 let Some(v) = cache.get("2") else {
311 return;
312 };
313 println!("cache.get(2): {:?}", v);
314 sleep(Duration::from_secs(6));
315 }
316
317 fn test_cache_evication() {
318 let _ = check_exp_interval();
319 insert("check_evication", "过期了value", Expiration::Second(5)).unwrap();
320 sleep(Duration::from_secs(3));
321 println!("sleep 3s");
322
323 let (_, v) = get::<_, String>("check_evication").unwrap();
324 println!("get_string:{:?}", v);
325 println!("sleep 3s");
326 sleep(Duration::from_secs(3));
327 println!("contains_key:{:?}", contains_key("check_evication"));
328 sleep(Duration::from_secs(3));
329 }
331
332 fn test_cache_delete() {
334 let key = "key_u64";
335 println!("sleep 3s");
338 sleep(Duration::from_secs(3));
339 println!("get_exp:{:?}", get_exp(key));
340 println!("update:");
343 remove(key);
344 sleep(Duration::from_secs(1));
345
346 println!("get_exp:{:?}", get_exp(key));
353 }
355
356 fn test_cache_refresh() {
358 let key = "key_u64";
359 println!("sleep 3s");
362 sleep(Duration::from_secs(3));
363 let Some(exp_at) = get_exp(key) else {
364 return;
365 };
366 println!("get_exp:{:?}", exp_at);
367 println!("del:");
370 remove(key);
371
372 println!("get_exp:{:?}", get_exp(key));
374 println!("sleep 3s");
377 sleep(Duration::from_secs(2));
378 println!("get_exp:{:?}", get_exp(key));
379 println!("sleep 5s");
382 sleep(Duration::from_secs(2));
383 println!("get_exp:{:?}", get_exp(key));
384 }
386
387 fn test_cache_refresh2() {
389 let key = "key_u64";
390 println!("sleep 2s");
393 sleep(Duration::from_secs(2));
394
395 println!("refresh: ");
396 refresh(key).expect("refresh error");
397
398 println!("sleep 5s");
399 sleep(Duration::from_secs(5));
400 println!("get_exp:{:?}", get_exp(key));
401 }
403}