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<u64>>;
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()
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}