mycommon-utils 0.1.2

Common utilities library for database operations, Redis caching and system utilities
Documentation
use redis::{Client, Commands, FromRedisValue, RedisResult, ToRedisArgs};
use std::num::NonZeroUsize;
use r2d2::PooledConnection;
use crate::error::{Error, Result};
use crate::database::config::REDIS_POOL;

/// Redis 工具类,封装了一些常用的 Redis 操作。

pub struct RedisUtil {
    connection: PooledConnection<Client>
}

impl RedisUtil {
    /// 构造函数,初始化 Redis 客户端。
    pub fn new() -> Result<RedisUtil> {
        // 提取配置和连接池,若获取失败则直接返回错误
        let client = REDIS_POOL.get().ok_or_else(|| {
            tracing::error!("Failed to get Redis connection pool");
            Error::NotFound()
        })?;

        // 获取连接,若失败则记录错误并返回错误
        let connection = client.get().map_err(|e| {
            tracing::error!("Failed to obtain Redis connection: {:?}", e);
            Error::NotFound()
        })?;

        // 成功获取连接,创建并返回 RedisUtil 实例
        Ok(RedisUtil {
            connection
        })
    }

    /// 同步设置 Redis 键值对。
    pub fn set<T: ToRedisArgs>(&mut self, key: &str, value: &T) -> RedisResult<bool> {
        let result = self.connection.set(key, value)?;
        Ok(result)
    }

    /// 同步设置带有过期时间的 Redis 键值对。
    pub fn set_with_expiry<T: ToRedisArgs>(&mut self, key: &str, value: &T, expiry_seconds: u64) -> RedisResult<()> {
        let result =self.connection.set_ex(key, value, expiry_seconds)?;
        Ok(result)
    }

    /// 同步为现有键设置过期时间。
    pub fn expire(&mut self, key: &str, expiry_seconds: i64) -> RedisResult<bool> {
        let result =self.connection.expire(key, expiry_seconds)?;
        Ok(result)
    }

    /// 同步获取 Redis 键对应的值。
    pub fn get<T: FromRedisValue>(&mut self,key: &str) -> RedisResult<Option<T>> {
        let value: Option<T> = self.connection.get(key)?;
        Ok(value)
    }

    /// 使用 Pipeline 进行批量操作(设置多个键值对)。
    pub fn pipeline_operations<T: ToRedisArgs>(&mut self, keys: Vec<&str>, values: Vec<&T>) -> RedisResult<()> {
        if keys.len() != values.len() {
            return Err(redis::RedisError::from((
                redis::ErrorKind::TypeError,
                "Keys and values must have the same length",
            )));
        }
        let mut pipe = redis::pipe();
        for (key, value) in keys.iter().zip(values.iter()) {
            pipe.set(*key, *value).ignore();
        }
        pipe.query::<()>(&mut self.connection)?;
        Ok(())
    }

    /// 检查键是否存在。
    /// 返回 true 表示键存在,false 表示键不存在。
    pub fn exists(&mut self, key: &str) -> RedisResult<bool> {
        let exists = self.connection.exists(key)?;
        Ok(exists)
    }

    /// 删除一个或多个键。
    /// 返回删除的键数量。
    pub fn del_vec(&mut self, keys: Vec<&str>) -> RedisResult<usize> {
        self.connection.del(keys)
    }
    /// 删除一个键。
    /// 返回删除的键数量。
    pub fn del(&mut self, key: &str) -> RedisResult<usize> {
        self.connection.del(key)
    }
    /// 获取键的剩余生存时间(TTL),单位为秒。
    pub fn ttl(&mut self, key: &str) -> RedisResult<isize> {
        self.connection.ttl(key)
    }

    /// 对整数类型的键进行原子自增操作。
    pub fn incr(&mut self, key: &str) -> RedisResult<isize> {
        self.connection.incr(key, 1)
    }

    /// 对整数类型的键进行原子自减操作。
    pub fn decr(&mut self, key: &str) -> RedisResult<isize> {
        self.connection.decr(key, 1)
    }

    /// 设置哈希类型的键值对。
    pub fn hset(&mut self, key: &str, field: &str, value: &str) -> RedisResult<()> {
        self.connection.hset(key, field, value)
    }

    /// 获取哈希类型键的值。
    pub fn hget(&mut self, key: &str, field: &str) -> RedisResult<Option<String>> {
        self.connection.hget(key, field)
    }

    /// 向列表左侧推入元素。
    pub fn lpush<T: FromRedisValue>(&mut self, key: &str, value: &str) -> RedisResult<T> {
        self.connection.lpush(key, value)
    }

    /// 从列表右侧弹出元素。
    pub fn rpop<T: ToString>(&mut self, key: &str, count: Option<usize>) -> RedisResult<Option<Vec<String>>> {
        let non_zero_count = count.and_then(NonZeroUsize::new);
        self.connection.rpop(key, non_zero_count)
    }
}

// 使用示例:
// let redis_util = Redis::new().unwrap();
// redis_util.set("1", "aaa").unwrap();
// println!("Set value to 'aaa'");