1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use crate::AggregateError;
use serde_json::Error;
use std::fmt::{Display, Formatter};

/// Errors for implementations of a persistent event store.
#[derive(Debug)]
pub enum PersistenceError {
    /// Optimistic locking conflict occurred while committing and aggregate.
    OptimisticLockError,
    /// An error occurred connecting to the database.
    ConnectionError(Box<dyn std::error::Error + Send + Sync + 'static>),
    /// Error occurred while attempting to deserialize data.
    DeserializationError(Box<dyn std::error::Error + Send + Sync + 'static>),
    /// An unexpected error occurred while accessing the database.
    UnknownError(Box<dyn std::error::Error + Send + Sync + 'static>),
}

impl Display for PersistenceError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            PersistenceError::OptimisticLockError => write!(f, "optimistic lock error"),
            PersistenceError::ConnectionError(error) => write!(f, "{}", error),
            PersistenceError::DeserializationError(error) => write!(f, "{}", error),
            PersistenceError::UnknownError(error) => write!(f, "{}", error),
        }
    }
}

impl std::error::Error for PersistenceError {}

impl<T: std::error::Error> From<PersistenceError> for AggregateError<T> {
    fn from(err: PersistenceError) -> Self {
        match err {
            PersistenceError::OptimisticLockError => AggregateError::AggregateConflict,
            PersistenceError::ConnectionError(error) => {
                AggregateError::DatabaseConnectionError(error)
            }
            PersistenceError::DeserializationError(error) => {
                AggregateError::DeserializationError(error)
            }
            PersistenceError::UnknownError(error) => AggregateError::UnexpectedError(error),
        }
    }
}

impl From<serde_json::Error> for PersistenceError {
    fn from(err: Error) -> Self {
        match err.classify() {
            serde_json::error::Category::Data | serde_json::error::Category::Syntax => {
                PersistenceError::DeserializationError(Box::new(err))
            }
            serde_json::error::Category::Io | serde_json::error::Category::Eof => {
                PersistenceError::UnknownError(Box::new(err))
            }
        }
    }
}