graft_client/
error.rs

1use std::fmt::Debug;
2
3use graft_core::{page::PageSizeErr, page_idx::ConvertToPageIdxErr};
4use graft_proto::common::v1::{GraftErr, GraftErrCode};
5use thiserror::Error;
6
7use crate::runtime::storage;
8
9#[derive(Error, Debug)]
10pub enum ClientErr {
11    #[error("graft error: {0}")]
12    GraftErr(#[from] GraftErr),
13
14    #[error("http request failed: {0}")]
15    HttpErr(#[from] ureq::Error),
16
17    #[error("failed to decode protobuf message")]
18    ProtobufDecodeErr,
19
20    #[error("failed to parse splinter: {0}")]
21    SplinterParseErr(#[from] splinter_rs::DecodeErr),
22
23    #[error("local storage error: {0}")]
24    StorageErr(#[from] storage::StorageErr),
25
26    #[error("io error: {0}")]
27    IoErr(std::io::ErrorKind),
28
29    #[error("invalid page index")]
30    ConvertToPageIdxErr(#[from] ConvertToPageIdxErr),
31
32    #[error("invalid page size")]
33    PageSizeErr(#[from] PageSizeErr),
34}
35
36impl From<http::Error> for ClientErr {
37    fn from(err: http::Error) -> Self {
38        Self::HttpErr(err.into())
39    }
40}
41
42impl From<std::io::Error> for ClientErr {
43    fn from(err: std::io::Error) -> Self {
44        // attempt to convert the io error to a ureq error
45        match ureq::Error::from(err) {
46            // if we get an io error back then we normalize it
47            ureq::Error::Io(ioerr) => Self::IoErr(ioerr.kind()),
48            // if we get a decompression error, unpack the wrapped io error
49            ureq::Error::Decompress(_, ioerr) => ioerr.into(),
50            // otherwise we use the ureq Error
51            other => Self::HttpErr(other),
52        }
53    }
54}
55
56impl From<prost::DecodeError> for ClientErr {
57    fn from(_: prost::DecodeError) -> Self {
58        ClientErr::ProtobufDecodeErr
59    }
60}
61
62impl ClientErr {
63    pub(crate) fn is_snapshot_missing(&self) -> bool {
64        match self {
65            Self::GraftErr(err) => err.code() == GraftErrCode::SnapshotMissing,
66            _ => false,
67        }
68    }
69
70    pub(crate) fn is_commit_rejected(&self) -> bool {
71        match self {
72            Self::GraftErr(err) => err.code() == GraftErrCode::CommitRejected,
73            _ => false,
74        }
75    }
76
77    pub(crate) fn is_auth_err(&self) -> bool {
78        match self {
79            Self::GraftErr(err) => err.code() == GraftErrCode::Unauthorized,
80            _ => false,
81        }
82    }
83
84    pub(crate) fn is_network_err(&self) -> bool {
85        match self {
86            Self::HttpErr(ureq::Error::Timeout(_)) => true,
87            Self::HttpErr(ureq::Error::ConnectionFailed) => true,
88            Self::HttpErr(ureq::Error::ConnectProxyFailed(_)) => true,
89            Self::HttpErr(ureq::Error::Io(_)) => true,
90            Self::GraftErr(err) => err.code() == GraftErrCode::ServiceUnavailable,
91            _ => false,
92        }
93    }
94}