use redis::aio::ConnectionManager;
use redis::AsyncCommands;
use crate::error::StorageError;
pub struct RedisClient {
manager: ConnectionManager,
}
impl RedisClient {
pub async fn new(redis_url: &str) -> Result<Self, StorageError> {
let client = redis::Client::open(redis_url)
.map_err(|e| StorageError::ConfigError(format!("Invalid Redis URL: {}", e)))?;
let manager = ConnectionManager::new(client)
.await
.map_err(|e| StorageError::ConfigError(format!("Failed to connect to Redis: {}", e)))?;
Ok(RedisClient { manager })
}
pub async fn set(&mut self, key: &str, value: &str, ttl_seconds: Option<u64>) -> Result<(), StorageError> {
let _: () = self.manager.set(key, value).await.map_err(|e| {
StorageError::ConfigError(format!("Redis SET failed: {}", e))
})?;
if let Some(ttl) = ttl_seconds {
let _: () = self.manager.expire(key, ttl as i64).await.map_err(|e| {
StorageError::ConfigError(format!("Redis EXPIRE failed: {}", e))
})?;
}
Ok(())
}
pub async fn get(&mut self, key: &str) -> Result<Option<String>, StorageError> {
let result: Option<String> = self.manager.get(key).await.map_err(|e| {
StorageError::ConfigError(format!("Redis GET failed: {}", e))
})?;
Ok(result)
}
pub async fn delete(&mut self, key: &str) -> Result<(), StorageError> {
let _: () = self.manager.del(key).await.map_err(|e| {
StorageError::ConfigError(format!("Redis DEL failed: {}", e))
})?;
Ok(())
}
pub async fn exists(&mut self, key: &str) -> Result<bool, StorageError> {
let result: bool = self.manager.exists(key).await.map_err(|e| {
StorageError::ConfigError(format!("Redis EXISTS failed: {}", e))
})?;
Ok(result)
}
pub fn session_key(session_id: &str) -> String {
format!("otherone:session:{}", session_id)
}
pub fn entry_key(session_id: &str, entry_id: &str) -> String {
format!("otherone:entry:{}:{}", session_id, entry_id)
}
pub fn default_ttl() -> u64 {
86400
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_session_key() {
let key = RedisClient::session_key("abc-123");
assert_eq!(key, "otherone:session:abc-123");
}
#[test]
fn test_entry_key() {
let key = RedisClient::entry_key("session-1", "entry-1");
assert_eq!(key, "otherone:entry:session-1:entry-1");
}
#[test]
fn test_default_ttl() {
assert_eq!(RedisClient::default_ttl(), 86400);
}
}