Skip to main content

cc_core/
redis.rs

1//! Redis 连接的初始化与多连接管理。
2//!
3//! 用 `::redis` 显式引用外部 crate,以区别于本模块 `crate::redis`。
4
5use std::collections::HashMap;
6
7use ::redis::aio::ConnectionManager;
8
9use crate::config::{Config, IntoRedisName, RedisConfig};
10
11/// 用单个配置建立一个带自动重连的连接管理器(可廉价 clone 共享)。
12pub async fn connect(cfg: &RedisConfig) -> anyhow::Result<ConnectionManager> {
13    let client = ::redis::Client::open(cfg.url.as_str())
14        .map_err(|e| anyhow::anyhow!("打开 Redis({}) 失败: {}", cfg.url, e))?;
15    let mgr = ConnectionManager::new(client)
16        .await
17        .map_err(|e| anyhow::anyhow!("连接 Redis({}) 失败: {}", cfg.url, e))?;
18    Ok(mgr)
19}
20
21/// 多个命名 Redis 连接的容器。
22pub struct RedisPools {
23    conns: HashMap<String, ConnectionManager>,
24}
25
26impl RedisPools {
27    /// 为配置里声明的每个 `[redis.<名字>]` 建立连接。
28    pub async fn from_config(cfg: &Config) -> anyhow::Result<Self> {
29        let mut conns = HashMap::new();
30        for (name, rc) in &cfg.redis {
31            conns.insert(name.clone(), connect(rc).await?);
32        }
33        Ok(Self { conns })
34    }
35
36    /// 按名取连接(克隆出一份句柄,底层连接共享)。
37    pub fn get(&self, name: impl IntoRedisName) -> Option<ConnectionManager> {
38        self.conns.get(&name.into_name()).cloned()
39    }
40
41    /// 按名取连接,不存在时报错。
42    pub fn require(&self, name: impl IntoRedisName) -> anyhow::Result<ConnectionManager> {
43        let name = name.into_name();
44        self.conns
45            .get(&name)
46            .cloned()
47            .ok_or_else(|| anyhow::anyhow!("未找到名为 `{}` 的 Redis 连接", name))
48    }
49
50    /// 获取默认连接(名字为 "default")。
51    pub fn default(&self) -> anyhow::Result<ConnectionManager> {
52        self.require("default")
53    }
54}