diff options
author | alyx <alyx@aleteoryx.me> | 2023-08-09 01:34:47 -0400 |
---|---|---|
committer | alyx <alyx@aleteoryx.me> | 2023-08-09 01:34:47 -0400 |
commit | 40372f0cf8a95f4d5bdf78fc522328b776482dbf (patch) | |
tree | d5c0b0ea655e685927ed6b96df777b28fb2856c2 /src | |
parent | d796f6762acb52cf2ab202d76382915064f0d534 (diff) | |
download | lfm_embed-40372f0cf8a95f4d5bdf78fc522328b776482dbf.tar.gz lfm_embed-40372f0cf8a95f4d5bdf78fc522328b776482dbf.tar.bz2 lfm_embed-40372f0cf8a95f4d5bdf78fc522328b776482dbf.zip |
fix packages, implement caching
Diffstat (limited to 'src')
-rw-r--r-- | src/cache.rs | 120 | ||||
-rw-r--r-- | src/deserialize.rs | 4 | ||||
-rw-r--r-- | src/lib.rs | 3 |
3 files changed, 125 insertions, 2 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() + } +} +*/ diff --git a/src/deserialize.rs b/src/deserialize.rs index 4cedc9f..a00ebcb 100644 --- a/src/deserialize.rs +++ b/src/deserialize.rs @@ -74,8 +74,8 @@ pub struct Artist { #[serde(default)] #[serde(rename = "image")] pub images: Vec<Image>, - pub #[serde(default)] - url: Option<Arc<str>> + #[serde(default)] + pub url: Option<Arc<str>> } #[derive(Deserialize, Debug)] @@ -1 +1,4 @@ +#![feature(entry_insert)] + mod deserialize; +mod cache; |