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
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use std::time::Duration;

#[derive(Debug, thiserror::Error, Clone)]
pub enum Error {
    #[error("Query parsing error: {0}")]
    QueryParsing(String),

    #[cfg(feature = "local")]
    #[error("Error in Tantivy: {0}")]
    Tantivy(std::sync::Arc<tantivy::TantivyError>),

    #[cfg(feature = "local")]
    #[error("Error opening Tantivy directory: {0:?}")]
    TantivyOpenDirectoryError(std::sync::Arc<tantivy::directory::error::OpenDirectoryError>),

    #[cfg(feature = "local")]
    #[error("Error parsing Tantivy query: {0:?}")]
    TantitvyQueryParsing(std::sync::Arc<tantivy::query::QueryParserError>),

    #[cfg(feature = "local")]
    #[error("Chain engine error: {0}")]
    ChainEngine(#[from] exocore_chain::engine::EngineError),

    #[error("Transport error: {0}")]
    Transport(#[from] exocore_transport::Error),

    #[error("Error in capnp serialization: {0}")]
    Serialization(#[from] exocore_core::capnp::Error),

    #[error("Protobuf error: {0}")]
    Proto(#[from] exocore_core::protos::Error),

    #[error("A protobuf field was expected, but was empty: {0}")]
    ProtoFieldExpected(&'static str),

    #[error("IO error of kind {0}")]
    IO(#[source] std::sync::Arc<std::io::Error>),

    #[error("Error from remote store: {0}")]
    Remote(String),

    #[error("Timeout error: {0:?} > {0:?}")]
    Timeout(Duration, Duration),

    #[error("Not connected to any store node")]
    NotConnected,

    #[error("Try to lock a mutex that was poisoned")]
    Poisoned,

    #[error("Query or mutation got cancelled")]
    Cancelled,

    #[error("Dropped or couldn't get locked")]
    Dropped,

    #[error("Other error occurred: {0}")]
    Other(String),

    #[error("A fatal error occurred: {0}")]
    Fatal(String),
}

impl Error {
    pub fn is_fatal(&self) -> bool {
        #![allow(clippy::match_like_matches_macro)]
        match self {
            Error::Fatal(_) | Error::Poisoned | Error::Dropped | Error::IO(_) => true,

            #[cfg(feature = "local")]
            Error::TantivyOpenDirectoryError(_) => true,

            #[cfg(feature = "local")]
            Error::ChainEngine(err) if err.is_fatal() => true,

            _ => false,
        }
    }
}

#[cfg(feature = "local")]
impl From<tantivy::TantivyError> for Error {
    fn from(err: tantivy::TantivyError) -> Self {
        Error::Tantivy(std::sync::Arc::new(err))
    }
}

#[cfg(feature = "local")]
impl From<tantivy::query::QueryParserError> for Error {
    fn from(err: tantivy::query::QueryParserError) -> Self {
        Error::TantitvyQueryParsing(std::sync::Arc::new(err))
    }
}

#[cfg(feature = "local")]
impl From<tantivy::directory::error::OpenDirectoryError> for Error {
    fn from(err: tantivy::directory::error::OpenDirectoryError) -> Self {
        Error::TantivyOpenDirectoryError(std::sync::Arc::new(err))
    }
}

impl From<prost::DecodeError> for Error {
    fn from(err: prost::DecodeError) -> Self {
        Error::Proto(err.into())
    }
}

impl From<prost::EncodeError> for Error {
    fn from(err: prost::EncodeError) -> Self {
        Error::Proto(err.into())
    }
}

impl From<std::io::Error> for Error {
    fn from(err: std::io::Error) -> Self {
        Error::IO(std::sync::Arc::new(err))
    }
}

impl<T> From<std::sync::PoisonError<T>> for Error {
    fn from(_err: std::sync::PoisonError<T>) -> Self {
        Error::Poisoned
    }
}