use std::error::Error;
use std::fmt;
pub type FactoryError = Box<dyn Error + Send + Sync + 'static>;
#[derive(Debug)]
pub enum PoolError {
Config(String),
Closed(String),
Timeout(String),
Exhausted(String),
ConnectionCreate {
message: String,
source: Option<FactoryError>,
},
CircuitOpen {
retry_after: f64,
},
InvalidRelease(String),
}
impl PoolError {
pub fn source_error(&self) -> Option<&(dyn Error + 'static)> {
match self {
PoolError::ConnectionCreate {
source: Some(e), ..
} => Some(&**e),
_ => None,
}
}
}
impl fmt::Display for PoolError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PoolError::Config(m)
| PoolError::Closed(m)
| PoolError::Timeout(m)
| PoolError::Exhausted(m)
| PoolError::InvalidRelease(m) => f.write_str(m),
PoolError::ConnectionCreate { message, .. } => f.write_str(message),
PoolError::CircuitOpen { retry_after } => {
write!(f, "circuit breaker is open; retry in ~{retry_after:.1}s")
}
}
}
}
impl Error for PoolError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
self.source_error()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn display_messages_match_wire_format() {
assert_eq!(PoolError::Config("bad".into()).to_string(), "bad");
assert_eq!(PoolError::Closed("x".into()).to_string(), "x");
assert_eq!(PoolError::Timeout("t".into()).to_string(), "t");
assert_eq!(PoolError::Exhausted("e".into()).to_string(), "e");
assert_eq!(PoolError::InvalidRelease("i".into()).to_string(), "i");
assert_eq!(
PoolError::CircuitOpen { retry_after: 2.34 }.to_string(),
"circuit breaker is open; retry in ~2.3s"
);
let cc = PoolError::ConnectionCreate {
message: "nope".into(),
source: None,
};
assert_eq!(cc.to_string(), "nope");
}
#[test]
fn connection_create_exposes_source() {
let inner: FactoryError = "boom".into();
let err = PoolError::ConnectionCreate {
message: "could not create".into(),
source: Some(inner),
};
assert_eq!(err.source().unwrap().to_string(), "boom");
assert_eq!(err.source_error().unwrap().to_string(), "boom");
assert!(PoolError::Timeout("t".into()).source().is_none());
assert!(format!("{err:?}").contains("ConnectionCreate"));
}
}