oxidite_cache/
redis.rs

1use async_trait::async_trait;
2use redis::{Client, AsyncCommands};
3use std::time::Duration;
4use serde::{Deserialize, Serialize};
5use crate::{Cache, Result};
6
7/// Redis cache backend
8pub struct RedisCache {
9    client: Client,
10    default_ttl: Option<Duration>,
11}
12
13impl RedisCache {
14    pub fn new(url: &str) -> Result<Self> {
15        let client = Client::open(url)
16            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
17        
18        Ok(Self {
19            client,
20            default_ttl: Some(Duration::from_secs(3600)),
21        })
22    }
23
24    pub fn with_default_ttl(url: &str, ttl: Duration) -> Result<Self> {
25        let client = Client::open(url)
26            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
27        
28        Ok(Self {
29            client,
30            default_ttl: Some(ttl),
31        })
32    }
33}
34
35#[async_trait]
36impl Cache for RedisCache {
37    async fn get<T>(&self, key: &str) -> Result<Option<T>>
38    where
39        T: for<'de> Deserialize<'de> + Send,
40    {
41        let mut conn = self.client.get_multiplexed_async_connection()
42            .await
43            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
44            
45        let result: Option<String> = conn.get(key)
46            .await
47            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
48            
49        if let Some(data) = result {
50            let value: T = serde_json::from_str(&data)
51                .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
52            Ok(Some(value))
53        } else {
54            Ok(None)
55        }
56    }
57
58    async fn set<T>(&self, key: &str, value: &T, ttl: Option<Duration>) -> Result<()>
59    where
60        T: Serialize + Send + Sync,
61    {
62        let mut conn = self.client.get_multiplexed_async_connection()
63            .await
64            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
65            
66        let data = serde_json::to_string(value)
67            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
68            
69        let ttl = ttl.or(self.default_ttl);
70        
71        if let Some(duration) = ttl {
72            let _: () = conn.set_ex(key, data, duration.as_secs() as u64)
73                .await
74                .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
75        } else {
76            let _: () = conn.set(key, data)
77                .await
78                .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
79        }
80        
81        Ok(())
82    }
83
84    async fn delete(&self, key: &str) -> Result<()> {
85        let mut conn = self.client.get_multiplexed_async_connection()
86            .await
87            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
88            
89        let _: () = conn.del(key)
90            .await
91            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
92            
93        Ok(())
94    }
95
96    async fn exists(&self, key: &str) -> Result<bool> {
97        let mut conn = self.client.get_multiplexed_async_connection()
98            .await
99            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
100            
101        let exists: bool = conn.exists(key)
102            .await
103            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
104            
105        Ok(exists)
106    }
107
108    async fn flush(&self) -> Result<()> {
109        let mut conn = self.client.get_multiplexed_async_connection()
110            .await
111            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
112            
113        let _: () = redis::cmd("FLUSHDB")
114            .query_async(&mut conn)
115            .await
116            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
117            
118        Ok(())
119    }
120}