hehe_store/traits/
cache.rs1use 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}