mongo-es 0.4.0

A MongoDB implementation of the cqrs-es event store.
Documentation
use cqrs_es::persist::PersistenceError;

#[derive(Debug)]
pub enum MongoAggregateError {
    OptimisticLock,
    ConnectionError(Box<dyn std::error::Error + Send + Sync + 'static>),
    DeserializationError(Box<dyn std::error::Error + Send + Sync + 'static>),
    UnknownError(Box<dyn std::error::Error + Send + Sync + 'static>),
}

impl From<mongodb::error::Error> for MongoAggregateError {
    fn from(error: mongodb::error::Error) -> Self {
        match error.kind.as_ref() {
            mongodb::error::ErrorKind::BsonDeserialization(_) => {
                MongoAggregateError::DeserializationError(Box::new(error))
            }
            mongodb::error::ErrorKind::InsertMany(e) => {
                if e.write_errors.iter().flatten().any(|err| err.code == 11000) {
                    MongoAggregateError::OptimisticLock
                } else {
                    MongoAggregateError::UnknownError(Box::new(error))
                }
            }
            mongodb::error::ErrorKind::Write(mongodb::error::WriteFailure::WriteError(err))
                if err.code == 11000 =>
            {
                MongoAggregateError::OptimisticLock
            }
            _ => MongoAggregateError::UnknownError(Box::new(error)),
        }
    }
}

impl From<mongodb::bson::de::Error> for MongoAggregateError {
    fn from(error: mongodb::bson::de::Error) -> Self {
        MongoAggregateError::DeserializationError(Box::new(error))
    }
}

impl From<mongodb::bson::document::ValueAccessError> for MongoAggregateError {
    fn from(error: mongodb::bson::document::ValueAccessError) -> Self {
        MongoAggregateError::DeserializationError(Box::new(error))
    }
}

impl From<MongoAggregateError> for PersistenceError {
    fn from(error: MongoAggregateError) -> Self {
        match error {
            MongoAggregateError::OptimisticLock => PersistenceError::OptimisticLockError,
            MongoAggregateError::ConnectionError(err) => PersistenceError::ConnectionError(err),
            MongoAggregateError::DeserializationError(err) => {
                PersistenceError::DeserializationError(err)
            }
            MongoAggregateError::UnknownError(err) => PersistenceError::UnknownError(err),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_maps_bson_deserialization_error() {
        let bson_error =
            mongodb::bson::from_bson::<u32>(mongodb::bson::bson!({ "foo": "bar" })).unwrap_err();
        let mongo_error: MongoAggregateError = bson_error.into();
        assert!(matches!(
            mongo_error,
            MongoAggregateError::DeserializationError(_)
        ));
    }

    #[test]
    fn test_maps_bson_value_access_error() {
        let doc = mongodb::bson::doc! { "foo": "bar" };
        let access_error = doc.get_i32("foo").unwrap_err();
        let mongo_error: MongoAggregateError = access_error.into();
        assert!(matches!(
            mongo_error,
            MongoAggregateError::DeserializationError(_)
        ));
    }
}