actix_cloud/memorydb/
interface.rs

1use std::time::Duration;
2
3use async_trait::async_trait;
4
5use crate::Result;
6
7#[async_trait]
8pub trait MemoryDB: Send + Sync {
9    async fn set(&self, key: &str, value: &str) -> Result<()>;
10    async fn get(&self, key: &str) -> Result<Option<String>>;
11    async fn get_del(&self, key: &str) -> Result<Option<String>>;
12    async fn get_ex(&self, key: &str, ttl: &Duration) -> Result<Option<String>>;
13    async fn set_ex(&self, key: &str, value: &str, ttl: &Duration) -> Result<()>;
14    async fn del(&self, key: &str) -> Result<bool>;
15    async fn expire(&self, key: &str, ttl: i64) -> Result<bool>;
16    async fn flush(&self) -> Result<()>;
17    async fn keys(&self, key: &str) -> Result<Vec<String>>;
18    async fn dels(&self, keys: &[String]) -> Result<u64>;
19    async fn ttl(&self, key: &str) -> Result<Option<i64>>;
20}
21
22#[cfg(test)]
23mod tests {
24    use std::time::Duration;
25    use tokio::time::sleep;
26
27    use super::*;
28    use crate::memorydb::default::DefaultBackend;
29
30    #[cfg(feature = "redis")]
31    async fn setup_redis() -> impl MemoryDB {
32        crate::memorydb::redis::RedisBackend::new("redis://127.0.0.1:6379/0")
33            .await
34            .unwrap()
35    }
36
37    fn setup_default() -> impl MemoryDB {
38        DefaultBackend::new(None)
39    }
40
41    #[tokio::test]
42    async fn test_normal() {
43        test_normal_fn("default", setup_default()).await;
44        #[cfg(feature = "redis")]
45        test_normal_fn("redis", setup_redis().await).await;
46    }
47
48    async fn test_normal_fn(name: &str, r: impl MemoryDB) {
49        let key = "_actix_cloud_key1";
50        let value1 = "value1";
51        let value2 = "value2";
52
53        println!("Backend: {}", name);
54
55        let _ = r.del(key).await;
56
57        assert_eq!(r.get(key).await.unwrap(), None);
58
59        r.set(key, value1).await.unwrap();
60        assert_eq!(r.get(key).await.unwrap().unwrap(), value1);
61        r.set(key, value2).await.unwrap();
62        assert_eq!(r.get(key).await.unwrap().unwrap(), value2);
63
64        assert_eq!(r.del(key).await.unwrap(), true);
65        assert_eq!(r.del(key).await.unwrap(), false);
66        assert_eq!(r.get(key).await.unwrap(), None);
67    }
68
69    #[tokio::test]
70    async fn test_ex() {
71        test_ex_fn("default", setup_default()).await;
72        #[cfg(feature = "redis")]
73        test_ex_fn("redis", setup_redis().await).await;
74    }
75
76    async fn test_ex_fn(name: &str, r: impl MemoryDB) {
77        let key = "_actix_cloud_key2";
78        let value = "value";
79
80        println!("Backend: {}", name);
81
82        let _ = r.del(key).await;
83
84        r.set(key, value).await.unwrap();
85        assert_eq!(r.ttl(key).await.unwrap(), None);
86        assert_eq!(r.get_del(key).await.unwrap().unwrap(), value);
87        assert_eq!(r.get(key).await.unwrap(), None);
88
89        r.set_ex(key, value, &Duration::from_secs(2)).await.unwrap();
90        assert_eq!(r.get(key).await.unwrap().unwrap(), value);
91        assert_eq!(r.ttl(key).await.unwrap(), Some(2));
92        sleep(Duration::from_secs(1)).await;
93        assert_eq!(r.ttl(key).await.unwrap(), Some(1));
94        assert_eq!(
95            r.get_ex(key, &Duration::from_secs(2))
96                .await
97                .unwrap()
98                .unwrap(),
99            value
100        );
101        assert_eq!(r.ttl(key).await.unwrap(), Some(2));
102        sleep(Duration::from_secs(1)).await;
103        assert_eq!(r.ttl(key).await.unwrap(), Some(1));
104        assert_eq!(r.get(key).await.unwrap().unwrap(), value);
105        sleep(Duration::from_secs(2)).await;
106        assert_eq!(r.ttl(key).await.unwrap(), None);
107        assert_eq!(r.get(key).await.unwrap(), None);
108    }
109
110    #[tokio::test]
111    async fn test_expire() {
112        test_expire_fn("default", setup_default()).await;
113        #[cfg(feature = "redis")]
114        test_expire_fn("redis", setup_redis().await).await;
115    }
116
117    async fn test_expire_fn(name: &str, r: impl MemoryDB) {
118        let key = "_actix_cloud_key3";
119        let value = "value";
120
121        println!("Backend: {}", name);
122
123        let _ = r.del(key).await;
124
125        r.set(key, value).await.unwrap();
126        assert_eq!(r.get(key).await.unwrap().unwrap(), value);
127        assert_eq!(r.expire(key, 1).await.unwrap(), true);
128        sleep(Duration::from_secs(2)).await;
129        assert_eq!(r.get(key).await.unwrap(), None);
130        assert_eq!(r.expire(key, 1).await.unwrap(), false);
131
132        r.set_ex(key, value, &Duration::from_secs(1)).await.unwrap();
133        assert_eq!(r.expire(key, 3).await.unwrap(), true);
134        sleep(Duration::from_secs(2)).await;
135        assert_eq!(r.get(key).await.unwrap().unwrap(), value);
136        assert_eq!(r.expire(key, -1).await.unwrap(), true);
137        assert_eq!(r.get(key).await.unwrap(), None);
138        assert_eq!(r.expire(key, 0).await.unwrap(), false);
139    }
140
141    #[tokio::test]
142    async fn test_batch() {
143        test_batch_fn("default", setup_default()).await;
144        #[cfg(feature = "redis")]
145        test_batch_fn("redis", setup_redis().await).await;
146    }
147
148    async fn test_batch_fn(name: &str, r: impl MemoryDB) {
149        let key1 = "_actix_cloud_bkey1";
150        let key2 = "_actix_cloud_bkey2";
151        let value = "value";
152
153        println!("Backend: {}", name);
154
155        let _ = r.del(key1).await;
156        let _ = r.del(key2).await;
157
158        r.set(key1, value).await.unwrap();
159        r.set(key2, value).await.unwrap();
160        let ret = r.keys("_actix_cl?ud_bkey*").await.unwrap();
161        assert_eq!(ret.len(), 2);
162        assert_eq!(
163            (ret[0] == key1 && ret[1] == key2) || (ret[1] == key1 && ret[0] == key2),
164            true
165        );
166        assert_eq!(
167            r.dels(&vec![key1.to_owned(), key2.to_owned()])
168                .await
169                .unwrap(),
170            2
171        );
172        assert_eq!(r.keys("_actix_cl?ud_bkey*").await.unwrap().len(), 0);
173    }
174
175    #[tokio::test]
176    async fn test_default_capacity() {
177        let key1 = "_actix_cloud_ckey1";
178        let key2 = "_actix_cloud_ckey2";
179        let key3 = "_actix_cloud_ckey3";
180        let value = "value";
181
182        let r = DefaultBackend::new(Some(2));
183        let _ = r.del(key1).await;
184        let _ = r.del(key2).await;
185        let _ = r.del(key3).await;
186
187        assert_eq!(r.set(key1, value).await.is_ok(), true);
188        assert_eq!(r.set(key2, value).await.is_ok(), true);
189        assert_eq!(r.set(key3, value).await.is_ok(), false);
190        assert_eq!(r.set(key1, value).await.is_ok(), true);
191        assert_eq!(r.set(key2, value).await.is_ok(), true);
192
193        assert_eq!(
194            r.set_ex(key2, value, &Duration::from_secs(1)).await.is_ok(),
195            true
196        );
197        sleep(Duration::from_secs(2)).await;
198        assert_eq!(r.set(key3, value).await.is_ok(), true);
199        assert_eq!(r.get(key1).await.unwrap().unwrap(), value);
200        assert_eq!(r.get(key2).await.unwrap(), None);
201
202        assert_eq!(
203            r.set_ex(key3, value, &Duration::from_secs(3)).await.is_ok(),
204            true
205        );
206        sleep(Duration::from_secs(1)).await;
207        assert_eq!(r.set(key2, value).await.is_ok(), true);
208        assert_eq!(r.get(key1).await.unwrap().unwrap(), value);
209        assert_eq!(r.get(key3).await.unwrap(), None);
210
211        assert_eq!(r.del(key1).await.unwrap(), true);
212        assert_eq!(r.del(key2).await.unwrap(), true);
213        assert_eq!(
214            r.set_ex(key1, value, &Duration::from_secs(3)).await.is_ok(),
215            true
216        );
217        assert_eq!(
218            r.set_ex(key2, value, &Duration::from_secs(2)).await.is_ok(),
219            true
220        );
221        assert_eq!(
222            r.set_ex(key3, value, &Duration::from_secs(2)).await.is_ok(),
223            true
224        );
225        assert_eq!(r.get(key1).await.unwrap().unwrap(), value);
226        assert_eq!(r.get(key2).await.unwrap(), None);
227        assert_eq!(r.get(key3).await.unwrap().unwrap(), value);
228
229        assert_eq!(r.del(key1).await.unwrap(), true);
230        assert_eq!(r.del(key3).await.unwrap(), true);
231    }
232}