File size: 2,371 Bytes
c71a680
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
use redis::AsyncCommands;
use std::sync::Arc;
use tokio::sync::Mutex;
use tracing::warn;

#[derive(Clone)]
pub struct CacheClient {
    inner: Option<Arc<Mutex<redis::aio::ConnectionManager>>>,
}

impl CacheClient {
    pub async fn new(redis_url: &str) -> Self {
        if redis_url.is_empty() {
            warn!("REDIS_URL not set \u{2014} cache disabled");
            return Self { inner: None };
        }
        match redis::Client::open(redis_url) {
            Ok(client) => match client.get_connection_manager().await {
                Ok(conn) => {
                    tracing::info!("Redis connected");
                    Self { inner: Some(Arc::new(Mutex::new(conn))) }
                }
                Err(e) => {
                    warn!("Redis connection failed (cache disabled): {e}");
                    Self { inner: None }
                }
            },
            Err(e) => {
                warn!("Redis URL invalid (cache disabled): {e}");
                Self { inner: None }
            }
        }
    }

    pub async fn get_string(&self, key: &str) -> Option<String> {
        let inner = self.inner.as_ref()?;
        let mut conn = inner.lock().await;
        conn.get(key).await.ok()
    }

    pub async fn set_string(&self, key: &str, val: &str, ttl_secs: u64) {
        let Some(inner) = &self.inner else { return };
        let mut conn = inner.lock().await;
        let _ = conn.set_ex::<_, _, ()>(key, val, ttl_secs).await;
    }

    pub async fn get_json(&self, key: &str) -> Option<serde_json::Value> {
        let s = self.get_string(key).await?;
        serde_json::from_str(&s).ok()
    }

    pub async fn set_json(&self, key: &str, val: &serde_json::Value, ttl_secs: u64) {
        if let Ok(s) = serde_json::to_string(val) {
            self.set_string(key, &s, ttl_secs).await;
        }
    }

    pub async fn del(&self, key: &str) {
        let Some(inner) = &self.inner else { return };
        let mut conn = inner.lock().await;
        let _ = conn.del::<_, ()>(key).await;
    }

    pub async fn del_pattern(&self, pattern: &str) {
        let Some(inner) = &self.inner else { return };
        let mut conn = inner.lock().await;
        let keys: Vec<String> = conn.keys(pattern).await.unwrap_or_default();
        if !keys.is_empty() {
            let _ = conn.del::<_, ()>(keys).await;
        }
    }
}