cloudflare_kv_proxy/
cache.rs

1use 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    /// Get value of a key.
31    pub async fn get<T: DeserializeOwned + Serialize>(&self, key: &str) -> Result<T> {
32        // try read cache
33        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        // raw get
39        let r = execute!(self.client.get(format!("{}{}", self.endpoint, key)));
40        // write cache only if success
41        if let Ok(r) = &r {
42            self.set_cache(key, r);
43        }
44        r
45    }
46
47    /// Clear all cached values.
48    pub fn clear_cached(&self) {
49        self.cache.inner.lock().clear()
50    }
51
52    /// Delete a single key value from cache only.
53    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}