#[derive(Debug, Clone, Copy)]
pub struct TransientPolicy<P> {
pub is_transient: P,
pub max_retries: usize,
}
impl<P> TransientPolicy<P> {
pub fn new(is_transient: P) -> Self {
Self {
is_transient,
max_retries: super::DEFAULT_MAX_TRANSIENT_RETRIES,
}
}
#[must_use]
pub fn with_max_retries(self, max_retries: usize) -> Self {
Self {
max_retries,
..self
}
}
}
pub(super) fn is_contention<E: std::error::Error + 'static>(error: &E) -> bool {
crate::errlanes::Fault::classify(error).is_contention()
}
#[cfg(test)]
mod tests {
use super::is_contention;
use crate::errlanes::{Transient, TransientKind};
#[derive(Debug, thiserror::Error)]
#[error("wrapped")]
struct Wrapped(#[source] Transient);
#[test]
fn contention_is_found_through_a_callers_wrapper() {
assert!(is_contention(&Wrapped(Transient::new(
TransientKind::Deadlock
))));
assert!(is_contention(&Wrapped(Transient::new(
TransientKind::SerializationFailure
))));
}
#[test]
fn other_transients_are_left_to_the_search() {
assert!(!is_contention(&Wrapped(Transient::new(
TransientKind::OptimisticConflict
))));
assert!(!is_contention(&Wrapped(Transient::new(
TransientKind::ConnectionLost
))));
assert!(!is_contention(&std::io::Error::other(
"not transient at all"
)));
}
}