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(_)
));
}
}