1use restate_sdk_shared_core::TerminalFailure;
20use std::error::Error as StdError;
21use std::fmt;
22
23#[derive(Debug)]
24pub(crate) enum HandlerErrorInner {
25 Retryable(Box<dyn StdError + Send + Sync + 'static>),
26 Terminal(TerminalErrorInner),
27}
28
29impl fmt::Display for HandlerErrorInner {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 match self {
32 HandlerErrorInner::Retryable(e) => {
33 write!(f, "Retryable error: {}", e)
34 }
35 HandlerErrorInner::Terminal(e) => fmt::Display::fmt(e, f),
36 }
37 }
38}
39
40impl StdError for HandlerErrorInner {
41 fn source(&self) -> Option<&(dyn StdError + 'static)> {
42 match self {
43 HandlerErrorInner::Retryable(e) => Some(e.as_ref()),
44 HandlerErrorInner::Terminal(e) => Some(e),
45 }
46 }
47}
48
49#[derive(Debug)]
52pub struct HandlerError(pub(crate) HandlerErrorInner);
53
54impl<E: Into<Box<dyn StdError + Send + Sync + 'static>>> From<E> for HandlerError {
55 fn from(value: E) -> Self {
56 Self(HandlerErrorInner::Retryable(value.into()))
57 }
58}
59
60impl From<TerminalError> for HandlerError {
61 fn from(value: TerminalError) -> Self {
62 Self(HandlerErrorInner::Terminal(value.0))
63 }
64}
65
66impl AsRef<dyn StdError + Send + Sync> for HandlerError {
68 fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
69 &self.0
70 }
71}
72
73impl AsRef<dyn StdError> for HandlerError {
74 fn as_ref(&self) -> &(dyn StdError + 'static) {
75 &self.0
76 }
77}
78
79#[derive(Debug, Clone)]
80pub(crate) struct TerminalErrorInner {
81 code: u16,
82 message: String,
83}
84
85impl fmt::Display for TerminalErrorInner {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 write!(f, "Terminal error [{}]: {}", self.code, self.message)
88 }
89}
90
91impl StdError for TerminalErrorInner {}
92
93#[derive(Debug, Clone)]
97pub struct TerminalError(pub(crate) TerminalErrorInner);
98
99impl TerminalError {
100 pub fn new(message: impl Into<String>) -> Self {
102 Self::new_with_code(500, message)
103 }
104
105 pub fn new_with_code(code: u16, message: impl Into<String>) -> Self {
107 Self(TerminalErrorInner {
108 code,
109 message: message.into(),
110 })
111 }
112
113 pub fn code(&self) -> u16 {
114 self.0.code
115 }
116
117 pub fn message(&self) -> &str {
118 &self.0.message
119 }
120
121 pub fn from_error<E: StdError>(e: E) -> Self {
122 Self::new(e.to_string())
123 }
124}
125
126impl fmt::Display for TerminalError {
127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128 fmt::Display::fmt(&self.0, f)
129 }
130}
131
132impl AsRef<dyn StdError + Send + Sync> for TerminalError {
133 fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
134 &self.0
135 }
136}
137
138impl AsRef<dyn StdError> for TerminalError {
139 fn as_ref(&self) -> &(dyn StdError + 'static) {
140 &self.0
141 }
142}
143
144impl From<TerminalFailure> for TerminalError {
145 fn from(value: TerminalFailure) -> Self {
146 Self(TerminalErrorInner {
147 code: value.code,
148 message: value.message,
149 })
150 }
151}
152
153impl From<TerminalError> for TerminalFailure {
154 fn from(value: TerminalError) -> Self {
155 Self {
156 code: value.0.code,
157 message: value.0.message,
158 }
159 }
160}
161
162pub type HandlerResult<T> = Result<T, HandlerError>;