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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//! Error types to use within handlers.

use restate_sdk_shared_core::Failure;
use std::error::Error as StdError;
use std::fmt;

#[derive(Debug)]
pub(crate) enum HandlerErrorInner {
    Retryable(Box<dyn StdError + Send + Sync + 'static>),
    Terminal(TerminalErrorInner),
}

impl fmt::Display for HandlerErrorInner {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            HandlerErrorInner::Retryable(e) => {
                write!(f, "Retryable error: {}", e)
            }
            HandlerErrorInner::Terminal(e) => fmt::Display::fmt(e, f),
        }
    }
}

impl StdError for HandlerErrorInner {
    fn source(&self) -> Option<&(dyn StdError + 'static)> {
        match self {
            HandlerErrorInner::Retryable(e) => Some(e.as_ref()),
            HandlerErrorInner::Terminal(e) => Some(e),
        }
    }
}

/// This error can contain either a [`TerminalError`], or any other Rust's [`StdError`].
/// For the latter, the error is considered "retryable", and the execution will be retried.
#[derive(Debug)]
pub struct HandlerError(pub(crate) HandlerErrorInner);

impl<E: Into<Box<dyn StdError + Send + Sync + 'static>>> From<E> for HandlerError {
    fn from(value: E) -> Self {
        Self(HandlerErrorInner::Retryable(value.into()))
    }
}

impl From<TerminalError> for HandlerError {
    fn from(value: TerminalError) -> Self {
        Self(HandlerErrorInner::Terminal(value.0))
    }
}

// Took from anyhow
impl AsRef<dyn StdError + Send + Sync> for HandlerError {
    fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
        &self.0
    }
}

impl AsRef<dyn StdError> for HandlerError {
    fn as_ref(&self) -> &(dyn StdError + 'static) {
        &self.0
    }
}

#[derive(Debug, Clone)]
pub(crate) struct TerminalErrorInner {
    code: u16,
    message: String,
}

impl fmt::Display for TerminalErrorInner {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Terminal error [{}]: {}", self.code, self.message)
    }
}

impl StdError for TerminalErrorInner {}

/// Error representing the result of an operation recorded in the journal.
///
/// When returned inside a [`crate::context::ContextSideEffects::run`] closure, or in a handler, it completes the operation with a failure value.
#[derive(Debug, Clone)]
pub struct TerminalError(pub(crate) TerminalErrorInner);

impl TerminalError {
    /// Create a new [`TerminalError`].
    pub fn new(message: impl Into<String>) -> Self {
        Self::new_with_code(500, message)
    }

    /// Create a new [`TerminalError`] with a status code.
    pub fn new_with_code(code: u16, message: impl Into<String>) -> Self {
        Self(TerminalErrorInner {
            code,
            message: message.into(),
        })
    }

    pub fn code(&self) -> u16 {
        self.0.code
    }

    pub fn message(&self) -> &str {
        &self.0.message
    }

    pub fn from_error<E: StdError>(e: E) -> Self {
        Self::new(e.to_string())
    }
}

impl fmt::Display for TerminalError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

impl AsRef<dyn StdError + Send + Sync> for TerminalError {
    fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
        &self.0
    }
}

impl AsRef<dyn StdError> for TerminalError {
    fn as_ref(&self) -> &(dyn StdError + 'static) {
        &self.0
    }
}

impl From<Failure> for TerminalError {
    fn from(value: Failure) -> Self {
        Self(TerminalErrorInner {
            code: value.code,
            message: value.message,
        })
    }
}

impl From<TerminalError> for Failure {
    fn from(value: TerminalError) -> Self {
        Self {
            code: value.0.code,
            message: value.0.message,
        }
    }
}

/// Result type for a Restate handler.
pub type HandlerResult<T> = Result<T, HandlerError>;