#![allow(dead_code)]
use anyhow::{Context, Result};
use redis::aio::MultiplexedConnection as RedisConnection;
use std::time::Duration;
#[derive(Debug)]
pub struct RedisService {
client: redis::Client,
url: String,
}
impl RedisService {
pub fn new(url: &str) -> Result<Self> {
let client =
redis::Client::open(url).with_context(|| format!("Failed to create Redis client for URL: {}", url))?;
Ok(Self {
client,
url: url.to_string(),
})
}
pub fn from_env() -> Result<Self> {
let url = std::env::var("MECHA10_REDIS_URL")
.or_else(|_| std::env::var("REDIS_URL"))
.unwrap_or_else(|_| "redis://localhost:6379".to_string());
Self::new(&url)
}
pub fn url(&self) -> &str {
&self.url
}
pub async fn get_connection(&self) -> Result<RedisConnection> {
self.client
.get_multiplexed_async_connection()
.await
.context("Failed to establish async Redis connection")
}
pub async fn get_multiplexed_connection(&self) -> Result<redis::aio::MultiplexedConnection> {
self.client
.get_multiplexed_async_connection()
.await
.context("Failed to establish multiplexed Redis connection")
}
pub async fn check_health(&self, timeout: Duration) -> bool {
match tokio::time::timeout(timeout, async {
let mut conn = self.get_multiplexed_connection().await?;
let _: String = redis::cmd("PING").query_async(&mut conn).await?;
Ok::<(), anyhow::Error>(())
})
.await
{
Ok(Ok(())) => true,
Ok(Err(_)) => false,
Err(_) => false, }
}
pub async fn is_healthy(&self) -> bool {
self.check_health(Duration::from_secs(2)).await
}
}
impl Default for RedisService {
fn default() -> Self {
Self::from_env().expect("Failed to create default Redis service")
}
}