1use std::{
2 borrow::Cow,
3 fmt::{Display, Formatter},
4};
5
6use crate::{
7 prelude::NodeId,
8 protocol::{
9 node::durable_message::DurableError,
10 node::raft::{raft_node::TcpNode, state_machine::topic::wait_ack::WaitAckError},
11 },
12};
13
14#[derive(Debug)]
15pub struct Error {
16 pub context: Cow<'static, str>,
17 pub kind: ErrorKind,
18}
19
20impl Display for Error {
21 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
22 write!(f, "{}: {:?}", self.context, self.kind)
23 }
24}
25
26impl std::error::Error for Error {}
27
28impl Error {
29 pub const fn contextual<T: Into<ErrorKind>>(
30 context: impl Into<Cow<'static, str>>,
31 ) -> impl FnOnce(T) -> Self {
32 move |kind| Self {
33 context: context.into(),
34 kind: kind.into(),
35 }
36 }
37 pub fn new(context: impl Into<Cow<'static, str>>, kind: impl Into<ErrorKind>) -> Self {
38 Self {
39 context: context.into(),
40 kind: kind.into(),
41 }
42 }
43 pub fn unknown(context: impl Into<Cow<'static, str>>) -> Self {
44 Self {
45 context: context.into(),
46 kind: ErrorKind::Custom("unknown error".into()),
47 }
48 }
49 pub fn custom(
50 context: impl Into<Cow<'static, str>>,
51 error: impl Into<Box<dyn std::error::Error + Send + Sync>>,
52 ) -> Self {
53 Self {
54 context: context.into(),
55 kind: ErrorKind::Custom(error.into()),
56 }
57 }
58 pub fn contextual_custom<E: std::error::Error + Send + Sync + 'static>(
59 context: impl Into<Cow<'static, str>>,
60 ) -> impl FnOnce(E) -> Self {
61 move |error| Self {
62 context: context.into(),
63 kind: ErrorKind::Custom(Box::new(error)),
64 }
65 }
66}
67
68macro_rules! error_kind {
69 (
70 pub enum $ErrorKind: ident {
71 $($Kind: ident$(: $InnerType: ty)?),*
72 }
73 ) => {
74 #[derive(Debug)]
75 pub enum ErrorKind {
76 $($Kind$(($InnerType))?,)*
77 }
78 $(
79 $(
80 impl From<$InnerType> for ErrorKind {
81 fn from(e: $InnerType) -> Self {
82 ErrorKind::$Kind(e)
83 }
84 }
85 )?
86 )*
87 };
88}
89error_kind! {
90 pub enum ErrorKind {
91 Durability: DurableError,
92 Offline,
93 TopicAlreadyExists,
94 NotLeader,
95 Io: std::io::Error,
96 Ack: WaitAckError,
97 Custom: Box<dyn std::error::Error + Send + Sync>,
98 RaftClient: openraft::error::RaftError<NodeId, openraft::error::ClientWriteError<NodeId, TcpNode>>,
99 Raft: openraft::error::RaftError<NodeId>
100 }
101}