use redis::aio::ConnectionManager;
use crate::error::{Error, Result};
use crate::extract::{FromRequest, RequestContext};
#[derive(Clone)]
pub struct Redis {
manager: ConnectionManager,
}
impl Redis {
pub async fn connect(url: &str) -> Result<Self> {
let client = redis::Client::open(url)
.map_err(|error| Error::internal(format!("invalid redis url: {error}")))?;
let manager = client
.get_connection_manager()
.await
.map_err(|error| Error::internal(format!("redis connection failed: {error}")))?;
Ok(Self { manager })
}
pub fn connection(&self) -> ConnectionManager {
self.manager.clone()
}
pub async fn query<T: redis::FromRedisValue>(&self, command: &redis::Cmd) -> Result<T> {
let mut conn = self.manager.clone();
command
.query_async(&mut conn)
.await
.map_err(|error| Error::internal(format!("redis command failed: {error}")))
}
}
impl FromRequest for Redis {
fn from_request(
ctx: &RequestContext,
) -> impl std::future::Future<Output = Result<Self>> + Send {
let resolved = ctx
.state()
.get::<Redis>()
.map(|redis| (*redis).clone())
.ok_or_else(|| {
Error::internal("redis is not configured; call `App::redis(...)` to enable it")
});
async move { resolved }
}
}