use crate::cache::redis::AppRedis; use crate::error::AppError; use super::SessionKey; use super::format::{deserialize_session_state, serialize_session_state}; use super::interface::{SessionState, SessionStore}; use super::utils::generate_session_key; pub struct RedisSessionStore { redis: AppRedis, } impl RedisSessionStore { pub fn new(redis: AppRedis) -> Self { Self { redis } } } impl SessionStore for RedisSessionStore { async fn load(&self, session_key: &SessionKey) -> Result, AppError> { let mut conn = self.redis.get_connection()?; let value: Option = redis::cmd("GET") .arg(session_key.as_ref()) .query(&mut *conn.inner_mut()) .ok() .flatten(); match value { None => Ok(None), Some(v) => Ok(Some(deserialize_session_state(&v)?)), } } async fn save( &self, session_state: SessionState, ttl_secs: u64, ) -> Result { let body = serialize_session_state(&session_state)?; let session_key = generate_session_key(); let mut conn = self.redis.get_connection()?; redis::cmd("SETEX") .arg(session_key.as_ref()) .arg(ttl_secs) .arg(&body) .query::<()>(&mut *conn.inner_mut())?; Ok(session_key) } async fn update( &self, session_key: SessionKey, session_state: SessionState, ttl_secs: u64, ) -> Result { let body = serialize_session_state(&session_state)?; let mut conn = self.redis.get_connection()?; redis::cmd("SETEX") .arg(session_key.as_ref()) .arg(ttl_secs) .arg(&body) .query::<()>(&mut *conn.inner_mut())?; Ok(session_key) } async fn update_ttl(&self, session_key: &SessionKey, ttl_secs: u64) -> Result<(), AppError> { let mut conn = self.redis.get_connection()?; redis::cmd("EXPIRE") .arg(session_key.as_ref()) .arg(ttl_secs) .query::<()>(&mut *conn.inner_mut())?; Ok(()) } async fn delete(&self, session_key: &SessionKey) -> Result<(), AppError> { let mut conn = self.redis.get_connection()?; redis::cmd("DEL") .arg(session_key.as_ref()) .query::<()>(&mut *conn.inner_mut())?; Ok(()) } }