redsync/
errors.rs

1use std::fmt;
2use std::ops::{Deref, DerefMut};
3
4use thiserror::Error;
5
6/// `RedsyncError` is an enum of all error kinds returned by the crate.
7#[derive(Error, Debug, PartialEq)]
8pub enum RedsyncError {
9    #[error("{0}")]
10    RedisError(#[from] redis::RedisError),
11    #[error("unexpected response from Redis: {0:?}")]
12    UnexpectedResponse(redis::Value),
13
14    #[error("requested resource is current locked")]
15    ResourceLocked,
16    #[error("invalid or expired lease on lock")]
17    InvalidLease,
18
19    #[error("lock attempt failed: max retries exceeded: {0}")]
20    LockRetriesExceeded(MultiError),
21    #[error("extend attempt failed: max retries exceeded: {0}")]
22    ExtendRetriesExceeded(MultiError),
23    #[error("unlock attempt failed: {0}")]
24    UnlockFailed(MultiError),
25}
26
27/// `MultiError` wraps `Vec<RedsyncError>`, typically aggregated over instances in a Redsync cluster.
28#[derive(Debug, Default, PartialEq)]
29pub struct MultiError(Vec<RedsyncError>);
30
31impl MultiError {
32    pub fn new() -> Self {
33        Default::default()
34    }
35
36    pub fn includes(&self, e: RedsyncError) -> bool {
37        self.contains(&e)
38    }
39
40    pub(crate) fn reset(&mut self) {
41        self.clear()
42    }
43}
44
45impl Deref for MultiError {
46    type Target = Vec<RedsyncError>;
47
48    fn deref(&self) -> &Self::Target {
49        &self.0
50    }
51}
52
53impl DerefMut for MultiError {
54    fn deref_mut(&mut self) -> &mut Self::Target {
55        &mut self.0
56    }
57}
58
59impl fmt::Display for MultiError {
60    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61        write!(f, "{} errors occurred:", self.len())?;
62        for error in self.iter() {
63            write!(f, "\n\t * {}", error)?;
64        }
65
66        Ok(())
67    }
68}