mecha10_cli_core/services/
redis.rs1#![allow(dead_code)]
2
3use anyhow::{Context, Result};
8use redis::aio::MultiplexedConnection as RedisConnection;
9use std::time::Duration;
10
11#[derive(Debug)]
12pub struct RedisService {
13 client: redis::Client,
14 url: String,
15}
16
17impl RedisService {
18 pub fn new(url: &str) -> Result<Self> {
20 let client =
21 redis::Client::open(url).with_context(|| format!("Failed to create Redis client for URL: {}", url))?;
22
23 Ok(Self {
24 client,
25 url: url.to_string(),
26 })
27 }
28
29 pub fn from_env() -> Result<Self> {
32 let url = std::env::var("MECHA10_REDIS_URL")
33 .or_else(|_| std::env::var("REDIS_URL"))
34 .unwrap_or_else(|_| "redis://localhost:6379".to_string());
35
36 Self::new(&url)
37 }
38
39 pub fn url(&self) -> &str {
41 &self.url
42 }
43
44 pub async fn get_connection(&self) -> Result<RedisConnection> {
47 self.client
48 .get_multiplexed_async_connection()
49 .await
50 .context("Failed to establish async Redis connection")
51 }
52
53 pub async fn get_multiplexed_connection(&self) -> Result<redis::aio::MultiplexedConnection> {
56 self.client
57 .get_multiplexed_async_connection()
58 .await
59 .context("Failed to establish multiplexed Redis connection")
60 }
61
62 pub async fn check_health(&self, timeout: Duration) -> bool {
64 match tokio::time::timeout(timeout, async {
65 let mut conn = self.get_multiplexed_connection().await?;
66 let _: String = redis::cmd("PING").query_async(&mut conn).await?;
67 Ok::<(), anyhow::Error>(())
68 })
69 .await
70 {
71 Ok(Ok(())) => true,
72 Ok(Err(_)) => false,
73 Err(_) => false,
74 }
75 }
76
77 pub async fn is_healthy(&self) -> bool {
79 self.check_health(Duration::from_secs(2)).await
80 }
81}
82
83impl Default for RedisService {
84 fn default() -> Self {
88 Self::from_env().expect("Failed to create default Redis service")
89 }
90}