cloudflare_kv_proxy/
cache.rs1use std::{ops::Add, sync::Arc};
2
3use coarsetime::{Duration, Instant};
4use hashlink::LruCache;
5use parking_lot::Mutex;
6use serde::{de::DeserializeOwned, Serialize};
7
8use crate::{Client, Result};
9
10#[derive(Debug)]
11pub(crate) struct Cache {
12 expire_ttl: Duration,
13 inner: Mutex<LruCache<String, Arc<CacheValue>>>,
14}
15
16#[derive(Debug, Clone)]
17pub(crate) struct CacheValue {
18 expire: Instant,
19 value: String,
20}
21
22pub(crate) fn new_cache(cache_size: usize, expire_ttl: Duration) -> Cache {
23 Cache {
24 expire_ttl,
25 inner: Mutex::new(LruCache::new(cache_size)),
26 }
27}
28
29impl Client {
30 pub async fn get<T: DeserializeOwned + Serialize>(&self, key: &str) -> Result<T> {
32 if let Some(cv) = self.get_cache(key) {
34 if let Ok(v) = serde_json::from_str(&cv.value) {
35 return Ok(v);
36 }
37 }
38 let r = execute!(self.client.get(format!("{}{}", self.endpoint, key)));
40 if let Ok(r) = &r {
42 self.set_cache(key, r);
43 }
44 r
45 }
46
47 pub fn clear_cached(&self) {
49 self.cache.inner.lock().clear()
50 }
51
52 pub fn prune_cached(&self, key: &str) {
54 self.cache.inner.lock().remove(key);
55 }
56
57 pub(crate) fn get_cache(&self, key: &str) -> Option<Arc<CacheValue>> {
58 let now = Instant::now();
59 let mut locked = self.cache.inner.lock();
60 let cv_ref = locked.get(key)?;
61 if cv_ref.expire < now {
62 return None;
63 }
64 let cv = cv_ref.to_owned();
65 Some(cv)
66 }
67
68 pub(crate) fn set_cache<T: Serialize + ?Sized>(&self, key: &str, data: &T) {
69 if let Ok(j) = serde_json::to_string(data) {
70 let cv = CacheValue {
71 expire: Instant::now().add(self.cache.expire_ttl),
72 value: j,
73 };
74 self.cache.inner.lock().insert(key.to_owned(), Arc::new(cv));
75 }
76 }
77}