aboutsummaryrefslogtreecommitdiffstats
path: root/src/cache.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/cache.rs')
-rw-r--r--src/cache.rs120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/cache.rs b/src/cache.rs
new file mode 100644
index 0000000..9089ff1
--- /dev/null
+++ b/src/cache.rs
@@ -0,0 +1,120 @@
+use std::{future::Future, time::*, collections::HashMap, hash::Hash};
+
+pub struct AsyncCache<K, V, F> {
+ func: F,
+ cache: HashMap<K, (Instant, V)>,
+ interval: Duration
+}
+
+impl<K, V, F, Fut> AsyncCache<K, V, F>
+where
+ F: for<'a> FnMut(&'a K) -> Fut,
+ K: Hash + PartialEq + Eq + Clone,
+ Fut: Future<Output = Result<V, &'static str>>
+{
+ pub fn new(interval: Duration, mut func: F) -> Self {
+ Self{
+ cache: HashMap::new(),
+ interval, func
+ }
+ }
+
+ pub async fn get(&mut self, key: &K) -> Result<&V, &'static str> {
+ if self.is_stale(&key) {
+ self.renew(&key).await
+ } else {
+ Ok(&self.cache.get(&key).unwrap().1)
+ }
+ }
+
+ pub async fn renew(&mut self, key: &K) -> Result<&V, &'static str> {
+ let val = (self.func)(&key).await?;
+ self.cache.insert(key.clone(), (Instant::now(), val));
+ Ok(&self.cache.get(key).unwrap().1)
+ }
+
+ pub fn is_stale(&self, key: &K) -> bool {
+ if let Some((last_update, _)) = self.cache.get(key) {
+ let now = Instant::now();
+ now < (*last_update + self.interval)
+ }
+ else { true }
+ }
+
+ pub async fn get_opt(&self, key: &K) -> Option<&V> {
+ if self.is_stale(key) {
+ self.cache.get(key).map(|(_, v)| v)
+ }
+ else { None }
+ }
+}
+
+impl<K, V, F, Fut> AsyncCache<K, V, F>
+where
+ F: for<'a> FnMut(&'a K) -> Fut,
+ K: Hash + PartialEq + Eq + Clone,
+ V: Clone,
+ Fut: Future<Output = Result<V, &'static str>>
+{
+ pub async fn get_owned(&mut self, key: &K) -> Result<V, &'static str> {
+ self.get(key).await.cloned()
+ }
+}
+/*
+pub struct AsyncCache<K, V, F> {
+ func: F,
+ cache: HashMap<K, (Instant, V)>,
+ interval: Duration
+}
+
+impl<K, V, F> AsyncCache<K, V, F>
+where
+ for<'a> F: FnMut(&'a K) -> Fut + 'a,
+ Fut: Future<Output = V>
+{
+ pub fn new(interval: Duration, mut func: F) -> Self {
+ Self{
+ cache: HashMap::new(),
+ interval, func
+ }
+ }
+
+ pub async fn get(&mut self, key: &K) -> &V {
+ if self.is_stale(key) {
+ self.renew().await
+ } else {
+ self.cache.get(key)
+ }
+ }
+
+ pub async fn renew(&mut self, key: &K) -> &V {
+ self.cache.get_mut(key).0 = now;
+ self.cache.get_mut(key).1 = (self.func)(key).await;
+ self.cache.get(key)
+ }
+
+ pub fn is_stale(&self, key: &K) -> bool {
+ let now = Instant::now();
+ let last_update = self.cache.get(key).0;
+ now < (last_update + self.interval)
+ }
+
+ pub fn get_opt(&self, key: &K) -> Option<&T> {
+ if self.is_stale(key) {
+ Some(self.cache.get(key))
+ }
+ else { None }
+ }
+}
+
+impl<K, V, F> AsyncCache<K, V, F>
+where
+ F: for<'a> FnMut(&'a K) -> Fut + 'a,
+ Fut: Future<Output = V>,
+ V: Clone
+{
+ pub async fn get_owned(&mut self, key: &K) -> V {
+ self.get(key).await.clone()
+ }
+}
+*/