mycommon_utils/database/
redis_util.rs1use redis::{Client, Commands, FromRedisValue, RedisResult, ToRedisArgs};
2use std::num::NonZeroUsize;
3use r2d2::PooledConnection;
4use crate::error::{Error, Result};
5use crate::database::config::REDIS_POOL;
6
7pub struct RedisUtil {
10 connection: PooledConnection<Client>
11}
12
13impl RedisUtil {
14 pub fn new() -> Result<RedisUtil> {
16 let client = REDIS_POOL.get().ok_or_else(|| {
18 tracing::error!("Failed to get Redis connection pool");
19 Error::NotFound()
20 })?;
21
22 let connection = client.get().map_err(|e| {
24 tracing::error!("Failed to obtain Redis connection: {:?}", e);
25 Error::NotFound()
26 })?;
27
28 Ok(RedisUtil {
30 connection
31 })
32 }
33
34 pub fn set<T: ToRedisArgs>(&mut self, key: &str, value: &T) -> RedisResult<bool> {
36 let result = self.connection.set(key, value)?;
37 Ok(result)
38 }
39
40 pub fn set_with_expiry<T: ToRedisArgs>(&mut self, key: &str, value: &T, expiry_seconds: u64) -> RedisResult<()> {
42 let result =self.connection.set_ex(key, value, expiry_seconds)?;
43 Ok(result)
44 }
45
46 pub fn set_nx_ex<T: ToRedisArgs>(&mut self, key: &str, value: &T, expiry_seconds: u64) -> RedisResult<bool> {
48 let mut cmd = redis::Cmd::set(key, value);
49 cmd.arg("NX").arg("EX").arg(expiry_seconds);
50 let result: String = cmd.query(&mut self.connection)?;
51 Ok(result == "OK")
52 }
53
54 pub fn expire(&mut self, key: &str, expiry_seconds: i64) -> RedisResult<bool> {
56 let result =self.connection.expire(key, expiry_seconds)?;
57 Ok(result)
58 }
59
60 pub fn get<T: FromRedisValue>(&mut self,key: &str) -> RedisResult<Option<T>> {
62 let value: Option<T> = self.connection.get(key)?;
63 Ok(value)
64 }
65
66 pub fn pipeline_operations<T: ToRedisArgs>(&mut self, keys: Vec<&str>, values: Vec<&T>) -> RedisResult<()> {
68 if keys.len() != values.len() {
69 return Err(redis::RedisError::from((
70 redis::ErrorKind::TypeError,
71 "Keys and values must have the same length",
72 )));
73 }
74 let mut pipe = redis::pipe();
75 for (key, value) in keys.iter().zip(values.iter()) {
76 pipe.set(*key, *value).ignore();
77 }
78 pipe.query::<()>(&mut self.connection)?;
79 Ok(())
80 }
81
82 pub fn exists(&mut self, key: &str) -> RedisResult<bool> {
85 let exists = self.connection.exists(key)?;
86 Ok(exists)
87 }
88
89 pub fn del_vec(&mut self, keys: Vec<&str>) -> RedisResult<usize> {
92 self.connection.del(keys)
93 }
94 pub fn del(&mut self, key: &str) -> RedisResult<usize> {
97 self.connection.del(key)
98 }
99 pub fn ttl(&mut self, key: &str) -> RedisResult<isize> {
101 self.connection.ttl(key)
102 }
103
104 pub fn incr(&mut self, key: &str) -> RedisResult<isize> {
106 self.connection.incr(key, 1)
107 }
108
109 pub fn decr(&mut self, key: &str) -> RedisResult<isize> {
111 self.connection.decr(key, 1)
112 }
113
114 pub fn hset(&mut self, key: &str, field: &str, value: &str) -> RedisResult<()> {
116 self.connection.hset(key, field, value)
117 }
118
119 pub fn hget(&mut self, key: &str, field: &str) -> RedisResult<Option<String>> {
121 self.connection.hget(key, field)
122 }
123
124 pub fn lpush<T: FromRedisValue>(&mut self, key: &str, value: &str) -> RedisResult<T> {
126 self.connection.lpush(key, value)
127 }
128
129 pub fn rpop<T: ToString>(&mut self, key: &str, count: Option<usize>) -> RedisResult<Option<Vec<String>>> {
131 let non_zero_count = count.and_then(NonZeroUsize::new);
132 self.connection.rpop(key, non_zero_count)
133 }
134}
135
136