actix_cloud/memorydb/
redis.rs1use std::time::Duration;
2
3use async_trait::async_trait;
4use redis::{aio::ConnectionManager, AsyncCommands, Expiry};
5
6use super::interface::MemoryDB;
7use crate::Result;
8
9#[derive(Clone)]
14pub struct RedisBackend {
15 client: ConnectionManager,
16}
17
18impl RedisBackend {
19 pub async fn new(dsn: &str) -> Result<Self> {
21 let client = ConnectionManager::new(redis::Client::open(dsn)?).await?;
22 Ok(Self { client })
23 }
24}
25
26#[async_trait]
27impl MemoryDB for RedisBackend {
28 async fn set(&self, key: &str, value: &str) -> Result<()> {
29 self.client
30 .clone()
31 .set(key, value)
32 .await
33 .map_err(Into::into)
34 }
35
36 async fn get(&self, key: &str) -> Result<Option<String>> {
37 self.client.clone().get(key).await.map_err(Into::into)
38 }
39
40 async fn get_del(&self, key: &str) -> Result<Option<String>> {
41 self.client.clone().get_del(key).await.map_err(Into::into)
42 }
43
44 async fn get_ex(&self, key: &str, ttl: &Duration) -> Result<Option<String>> {
45 self.client
46 .clone()
47 .get_ex(key, Expiry::PX(ttl.as_millis().try_into()?))
48 .await
49 .map_err(Into::into)
50 }
51
52 async fn set_ex(&self, key: &str, value: &str, ttl: &Duration) -> Result<()> {
53 self.client
54 .clone()
55 .pset_ex(key, value, ttl.as_millis().try_into()?)
56 .await
57 .map_err(Into::into)
58 }
59
60 async fn del(&self, key: &str) -> Result<bool> {
61 self.client.clone().del(key).await.map_err(Into::into)
62 }
63
64 async fn expire(&self, key: &str, ttl: &Duration) -> Result<bool> {
65 self.client
66 .clone()
67 .pexpire(key, ttl.as_millis().try_into()?)
68 .await
69 .map_err(Into::into)
70 }
71
72 async fn flush(&self) -> Result<()> {
73 redis::cmd("FLUSHDB")
74 .query_async(&mut self.client.clone())
75 .await
76 .map_err(Into::into)
77 }
78
79 async fn keys(&self, key: &str) -> Result<Vec<String>> {
80 self.client.clone().keys(key).await.map_err(Into::into)
81 }
82
83 async fn dels(&self, keys: &[String]) -> Result<u64> {
84 let mut p = redis::pipe();
85 let mut p = p.atomic();
86 for i in keys {
87 p = p.del(i);
88 }
89 let res: Vec<u64> = p.query_async(&mut self.client.clone()).await?;
90 Ok(res.into_iter().sum())
91 }
92
93 async fn ttl(&self, key: &str) -> Result<Option<Duration>> {
94 let ret: i64 = self.client.clone().pttl(key).await?;
95 if ret < 0 {
96 Ok(None)
97 } else {
98 Ok(Some(Duration::from_millis(ret.try_into()?)))
99 }
100 }
101}