use std::sync::Arc;
use redis::Client;
use redis::aio::ConnectionManager;
use crate::error::{PersistenceError, PersistenceResult};
#[derive(Clone)]
pub struct RedisPersistence {
manager: Arc<ConnectionManager>,
}
impl RedisPersistence {
fn from_manager(manager: ConnectionManager) -> Self {
Self {
manager: Arc::new(manager),
}
}
pub fn manager(&self) -> &ConnectionManager {
&self.manager
}
pub fn lock(&self) -> super::RedisLock {
super::RedisLock::new(Arc::clone(&self.manager))
}
pub fn checkpointer<S>(&self) -> super::RedisCheckpointer<S>
where
S: Clone + Send + Sync + serde::Serialize + serde::de::DeserializeOwned + 'static,
{
super::RedisCheckpointer::new(Arc::clone(&self.manager))
}
pub fn store<V>(&self) -> super::RedisStore<V>
where
V: Clone + Send + Sync + serde::Serialize + serde::de::DeserializeOwned + 'static,
{
super::RedisStore::new(Arc::clone(&self.manager))
}
pub fn session_log(&self) -> super::RedisSessionLog {
super::RedisSessionLog::new(Arc::clone(&self.manager))
}
pub fn builder() -> RedisPersistenceBuilder {
RedisPersistenceBuilder { url: None }
}
}
#[derive(Debug)]
#[must_use]
pub struct RedisPersistenceBuilder {
url: Option<String>,
}
impl RedisPersistenceBuilder {
pub fn with_connection_string(mut self, url: impl Into<String>) -> Self {
self.url = Some(url.into());
self
}
pub async fn connect(self) -> PersistenceResult<RedisPersistence> {
let url = self
.url
.ok_or_else(|| PersistenceError::Config("connection_string is required".into()))?;
let client = Client::open(url.as_str())
.map_err(|e| PersistenceError::Backend(format!("client open: {e}")))?;
let manager = ConnectionManager::new(client)
.await
.map_err(|e| PersistenceError::Backend(format!("connection manager: {e}")))?;
Ok(RedisPersistence::from_manager(manager))
}
}