1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
use crate::cache::Cache; use async_trait::async_trait; use ttl_cache::TtlCache; use std::hash::Hash; use std::time::Duration; pub struct DefaultCache<K, V> where K: Eq + Hash + Send + Sync + 'static, V: Send + Sync + 'static, { pub ttl: Duration, cache: TtlCache<K, V>, } impl<K, V> DefaultCache<K, V> where K: Eq + Hash + Send + Sync + 'static, V: Send + Sync + 'static, { pub fn new(cap: usize) -> DefaultCache<K, V> { DefaultCache { ttl: Duration::from_secs(120), cache: TtlCache::new(cap), } } } #[async_trait] impl<K, V> Cache<K, V> for DefaultCache<K, V> where K: Eq + Hash + Send + Sync + 'static, V: Send + Sync + 'static, { fn set_capacity(&mut self, cap: usize) { self.cache.set_capacity(cap); } fn set_ttl(&mut self, ttl: Duration) { self.ttl = ttl; } async fn get<'a>(&'a self, k: &K) -> Option<&'a V> { self.cache.get(k) } async fn has(&self, k: &K) -> bool { self.cache.contains_key(k) } async fn set(&mut self, k: K, v: V) { if self.has(&k).await { self.cache.remove(&k); } self.cache.insert(k, v, self.ttl); } async fn clear(&mut self) { self.cache.clear(); } } #[cfg(test)] mod tests { use super::*; use std::thread::sleep; #[cfg_attr(feature = "runtime-async-std", async_std::test)] #[cfg_attr(feature = "runtime-tokio", tokio::test)] async fn test_set_and_get() { let mut cache = DefaultCache::new(1); cache.set(vec!["alice", "/data1", "read"], false).await; assert!(cache.get(&vec!["alice", "/data1", "read"]).await == Some(&false)); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] #[cfg_attr(feature = "runtime-tokio", tokio::test)] async fn test_set_ttl() { let mut cache = DefaultCache::new(1); cache.set_ttl(Duration::from_secs(2)); cache.set(vec!["alice", "/data1", "read"], false).await; sleep(Duration::from_secs(1)); assert!(cache.get(&vec!["alice", "/data1", "read"]).await == Some(&false)); sleep(Duration::from_secs(2)); assert!(!cache.has(&vec!["alice", "/data1", "read"]).await); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] #[cfg_attr(feature = "runtime-tokio", tokio::test)] async fn test_capacity() { let mut cache = DefaultCache::new(1); cache.set(vec!["alice", "/data1", "read"], false).await; cache.set(vec!["bob", "/data2", "write"], false).await; assert!(!cache.has(&vec!["alice", "/data1", "read"]).await); assert!(cache.has(&vec!["bob", "/data2", "write"]).await); } #[cfg_attr(feature = "runtime-async-std", async_std::test)] #[cfg_attr(feature = "runtime-tokio", tokio::test)] async fn test_set_capacity() { let mut cache = DefaultCache::new(1); cache.set_capacity(2); cache.set(vec!["alice", "/data1", "read"], false).await; cache.set(vec!["bob", "/data2", "write"], false).await; cache .set(vec!["unknow", "/data3", "read_write"], false) .await; assert!(!cache.has(&vec!["alice", "/data1", "read"]).await); assert!(cache.has(&vec!["bob", "/data2", "write"]).await); assert!(cache.has(&vec!["unknow", "/data3", "read_write"]).await); } }