hehe_store/traits/
cache.rs

1use crate::error::Result;
2use async_trait::async_trait;
3use std::time::Duration;
4
5#[async_trait]
6pub trait CacheStore: Send + Sync {
7    async fn get(&self, key: &str) -> Result<Option<Vec<u8>>>;
8
9    async fn get_string(&self, key: &str) -> Result<Option<String>> {
10        match self.get(key).await? {
11            Some(data) => Ok(Some(
12                String::from_utf8(data).map_err(|e| crate::error::StoreError::internal(e.to_string()))?,
13            )),
14            None => Ok(None),
15        }
16    }
17
18    async fn set(&self, key: &str, value: &[u8], ttl: Option<Duration>) -> Result<()>;
19
20    async fn set_string(&self, key: &str, value: &str, ttl: Option<Duration>) -> Result<()> {
21        self.set(key, value.as_bytes(), ttl).await
22    }
23
24    async fn delete(&self, key: &str) -> Result<bool>;
25
26    async fn exists(&self, key: &str) -> Result<bool>;
27
28    async fn mget(&self, keys: &[&str]) -> Result<Vec<Option<Vec<u8>>>>;
29
30    async fn mset(&self, entries: &[(&str, &[u8])], ttl: Option<Duration>) -> Result<()>;
31
32    async fn incr(&self, key: &str, delta: i64) -> Result<i64>;
33
34    async fn decr(&self, key: &str, delta: i64) -> Result<i64> {
35        self.incr(key, -delta).await
36    }
37
38    async fn expire(&self, key: &str, ttl: Duration) -> Result<bool>;
39
40    async fn ttl(&self, key: &str) -> Result<Option<Duration>>;
41
42    async fn keys(&self, pattern: &str) -> Result<Vec<String>>;
43
44    async fn clear(&self) -> Result<()>;
45
46    async fn len(&self) -> Result<usize>;
47
48    fn backend_name(&self) -> &'static str;
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    struct MockCache;
56
57    #[async_trait]
58    impl CacheStore for MockCache {
59        async fn get(&self, _key: &str) -> Result<Option<Vec<u8>>> {
60            Ok(Some(b"test".to_vec()))
61        }
62        async fn set(&self, _key: &str, _value: &[u8], _ttl: Option<Duration>) -> Result<()> {
63            Ok(())
64        }
65        async fn delete(&self, _key: &str) -> Result<bool> {
66            Ok(true)
67        }
68        async fn exists(&self, _key: &str) -> Result<bool> {
69            Ok(true)
70        }
71        async fn mget(&self, keys: &[&str]) -> Result<Vec<Option<Vec<u8>>>> {
72            Ok(keys.iter().map(|_| Some(b"test".to_vec())).collect())
73        }
74        async fn mset(&self, _entries: &[(&str, &[u8])], _ttl: Option<Duration>) -> Result<()> {
75            Ok(())
76        }
77        async fn incr(&self, _key: &str, delta: i64) -> Result<i64> {
78            Ok(delta)
79        }
80        async fn expire(&self, _key: &str, _ttl: Duration) -> Result<bool> {
81            Ok(true)
82        }
83        async fn ttl(&self, _key: &str) -> Result<Option<Duration>> {
84            Ok(Some(Duration::from_secs(60)))
85        }
86        async fn keys(&self, _pattern: &str) -> Result<Vec<String>> {
87            Ok(vec!["key1".into(), "key2".into()])
88        }
89        async fn clear(&self) -> Result<()> {
90            Ok(())
91        }
92        async fn len(&self) -> Result<usize> {
93            Ok(0)
94        }
95        fn backend_name(&self) -> &'static str {
96            "mock"
97        }
98    }
99
100    #[tokio::test]
101    async fn test_cache_trait() {
102        let cache = MockCache;
103
104        let data = cache.get("key").await.unwrap();
105        assert_eq!(data, Some(b"test".to_vec()));
106
107        assert!(cache.exists("key").await.unwrap());
108        assert!(cache.delete("key").await.unwrap());
109    }
110
111    #[tokio::test]
112    async fn test_string_helpers() {
113        let cache = MockCache;
114
115        let s = cache.get_string("key").await.unwrap();
116        assert_eq!(s, Some("test".into()));
117
118        cache.set_string("key", "value", None).await.unwrap();
119    }
120}