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}