use std::error::Error; use std::fmt::{self, Display, Formatter}; use cache::CacheError; use cache::redis::RedisError; #[derive(Debug)] pub enum SessionError { Serialize { key: String, source: serde_json::Error, }, Deserialize { key: String, source: serde_json::Error, }, Purged, UpdateConflict { key: String, }, Config(String), Store(CacheError), Backend(RedisError), } impl SessionError { pub fn config(message: impl Into) -> Self { Self::Config(message.into()) } pub fn serialize(key: impl Into, source: serde_json::Error) -> Self { Self::Serialize { key: key.into(), source, } } pub fn deserialize(key: impl Into, source: serde_json::Error) -> Self { Self::Deserialize { key: key.into(), source, } } pub fn conflict(key: impl Into) -> Self { Self::UpdateConflict { key: key.into() } } pub fn is_purged(&self) -> bool { matches!(self, Self::Purged) } pub fn is_retryable(&self) -> bool { matches!(self, Self::Store(source) if source.is_retryable()) } } impl Display for SessionError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Self::Serialize { key, source } => { write!(f, "failed to serialize session field `{key}`: {source}") } Self::Deserialize { key, source } => { write!(f, "failed to deserialize session field `{key}`: {source}") } Self::Purged => f.write_str("session record has been purged"), Self::UpdateConflict { key } => { write!( f, "session field `{key}` changed before its update was committed" ) } Self::Config(message) => write!(f, "invalid session configuration: {message}"), Self::Store(source) => write!(f, "session store error: {source}"), Self::Backend(source) => write!(f, "session backend error: {source}"), } } } impl Error for SessionError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { Self::Serialize { source, .. } | Self::Deserialize { source, .. } => Some(source), Self::Store(source) => Some(source), Self::Backend(source) => Some(source), Self::Purged | Self::UpdateConflict { .. } | Self::Config(_) => None, } } } impl From for SessionError { fn from(value: CacheError) -> Self { Self::Store(value) } } impl From for SessionError { fn from(value: RedisError) -> Self { Self::Backend(value) } }