1use std::fmt;
4use std::sync::Arc;
5
6pub type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
8pub type SharedError = Arc<dyn std::error::Error + Send + Sync + 'static>;
10
11#[derive(Debug, Clone)]
18pub enum Error {
19 Source(SharedError),
22 FallbackTimeout(Arc<FallbackTimeout>),
25 Panic(Arc<str>),
27 Config(ConfigError),
29 MissingRemote,
31 Remote(SharedError),
33}
34
35impl Error {
36 pub fn source_error(&self) -> Option<&(dyn std::error::Error + Send + Sync + 'static)> {
38 match self {
39 Error::Source(error) => Some(error.as_ref()),
40 _ => None,
41 }
42 }
43
44 pub fn is_fallback_timeout(&self) -> bool {
48 match self {
49 Error::FallbackTimeout(_) => true,
50 Error::Source(error) => {
51 error.downcast_ref::<FallbackTimeout>().is_some()
52 || error
53 .downcast_ref::<Error>()
54 .is_some_and(Error::is_fallback_timeout)
55 }
56 _ => false,
57 }
58 }
59}
60
61impl fmt::Display for Error {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 match self {
64 Error::Source(error) => write!(f, "DialCache source failed: {error}"),
65 Error::FallbackTimeout(timeout) => timeout.fmt(f),
66 Error::Panic(message) => write!(f, "DialCache callback panicked: {message}"),
67 Error::Config(error) => error.fmt(f),
68 Error::MissingRemote => {
69 f.write_str("DialCache invalidation requires a configured remote adapter")
70 }
71 Error::Remote(error) => write!(f, "DialCache remote maintenance failed: {error}"),
72 }
73 }
74}
75
76impl std::error::Error for Error {
77 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
78 match self {
79 Error::Source(error) | Error::Remote(error) => Some(error.as_ref()),
80 Error::FallbackTimeout(timeout) => Some(timeout.as_ref()),
81 Error::Config(error) => Some(error),
82 _ => None,
83 }
84 }
85}
86
87impl From<ConfigError> for Error {
88 fn from(error: ConfigError) -> Self {
89 Error::Config(error)
90 }
91}
92
93#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
95#[error("DialCache fallback for use case {use_case:?} timed out after {timeout_ms} ms")]
96pub struct FallbackTimeout {
97 pub use_case: String,
99 pub timeout_ms: u64,
101}
102
103#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
105#[error("DialCache remote read for use case {use_case:?} timed out after {timeout_ms} ms")]
106pub struct RemoteReadTimeout {
107 pub use_case: String,
109 pub timeout_ms: u64,
111}
112
113#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
115pub enum ConfigError {
116 #[error("{0}")]
118 Invalid(String),
119 #[error("DialCache use case name is reserved: {0}")]
121 ReservedUseCase(String),
122 #[error("DialCache use case already registered: {0}")]
124 UseCaseAlreadyRegistered(String),
125}
126
127impl ConfigError {
128 pub(crate) fn invalid(message: impl Into<String>) -> Self {
129 ConfigError::Invalid(message.into())
130 }
131}