zeebe_rs/
throw_error.rs

1use crate::{Client, ClientError, proto};
2use serde::Serialize;
3
4pub struct Initial;
5pub struct WithKey;
6pub struct WithCode;
7
8pub trait ThrowErrorRequestState {}
9impl ThrowErrorRequestState for Initial {}
10impl ThrowErrorRequestState for WithKey {}
11impl ThrowErrorRequestState for WithCode {}
12
13/// Request to throw a business error for a job
14///
15/// The error will be caught by an error catch event in the process.
16/// If no matching catch event exists, an incident will be raised instead.
17///
18/// # Examples
19/// ```ignore
20/// client
21///     .throw_error()
22///     .with_job_key(123456)
23///     .with_error_code(String::from("error_code"))
24///     .send()
25///     .await?;
26/// ```
27#[derive(Debug, Clone)]
28pub struct ThrowErrorRequest<T: ThrowErrorRequestState> {
29    client: Client,
30    job_key: i64,
31    error_code: String,
32    error_message: String,
33    variables: serde_json::Value,
34    _state: std::marker::PhantomData<T>,
35}
36
37impl<T: ThrowErrorRequestState> ThrowErrorRequest<T> {
38    pub(crate) fn new(client: Client) -> ThrowErrorRequest<Initial> {
39        ThrowErrorRequest {
40            client,
41            job_key: 0,
42            error_code: String::new(),
43            error_message: String::new(),
44            variables: serde_json::Value::default(),
45            _state: std::marker::PhantomData,
46        }
47    }
48
49    fn transition<NewState: ThrowErrorRequestState>(self) -> ThrowErrorRequest<NewState> {
50        ThrowErrorRequest {
51            client: self.client,
52            job_key: self.job_key,
53            error_code: self.error_code,
54            error_message: self.error_message,
55            variables: self.variables,
56            _state: std::marker::PhantomData,
57        }
58    }
59}
60
61impl ThrowErrorRequest<Initial> {
62    /// Sets the job key for which to throw the error
63    ///
64    /// # Arguments
65    /// * `job_key` - Unique job identifier from job activation
66    ///
67    /// # Returns
68    /// A `ThrowErrorRequest` in the `WithKey` state
69    pub fn with_job_key(mut self, job_key: i64) -> ThrowErrorRequest<WithKey> {
70        self.job_key = job_key;
71        self.transition()
72    }
73}
74
75impl ThrowErrorRequest<WithKey> {
76    /// Sets the error code that will match an error catch event
77    ///
78    /// # Arguments
79    /// * `error_code` - Code that will be matched with an error catch event in the process
80    ///
81    /// # Returns
82    /// A `ThrowErrorRequest` in the `WithCode` state
83    pub fn with_error_code(mut self, error_code: String) -> ThrowErrorRequest<WithCode> {
84        self.error_code = error_code;
85        self.transition()
86    }
87}
88
89impl ThrowErrorRequest<WithCode> {
90    /// Sets an optional message describing the error
91    ///
92    /// # Arguments
93    /// * `error_message` - Additional context about the error
94    ///
95    /// # Returns
96    /// The updated `ThrowErrorRequest` with the error message set
97    pub fn with_error_message(mut self, error_message: String) -> Self {
98        self.error_message = error_message;
99        self
100    }
101
102    /// Sets variables that will be available in the error catch event scope
103    ///
104    /// # Arguments
105    /// * `data` - Variables as serializable type that will be converted to JSON
106    ///     JSON document that will instantiate the variables at the local scope of the
107    ///     error catch event that catches the thrown error; it must be a JSON object, as variables will be mapped in a
108    ///     key-value fashion. e.g. { "a": 1, "b": 2 } will create two variables, named "a" and
109    ///     "b" respectively, with their associated values. [{ "a": 1, "b": 2 }] would not be a
110    ///     valid argument, as the root of the JSON document is an array and not an object.
111    ///
112    /// # Errors
113    /// Returns `ClientError` if serialization fails
114    ///
115    /// # Returns
116    /// A `Result` containing the updated `ThrowErrorRequest` with the variables set, or a `ClientError`
117    pub fn with_variables<T: Serialize>(mut self, data: T) -> Result<Self, ClientError> {
118        self.variables = serde_json::to_value(data)?;
119        Ok(self)
120    }
121
122    /// Sends the throw error request to the gateway
123    ///
124    /// # Errors
125    /// - `NOT_FOUND`: No job exists with given key
126    /// - `FAILED_PRECONDITION`: Job is not in activated state
127    ///
128    /// # Returns
129    /// A `Result` containing a `ThrowErrorResponse` or a `ClientError`
130    pub async fn send(mut self) -> Result<ThrowErrorResponse, ClientError> {
131        let res = self
132            .client
133            .gateway_client
134            .throw_error(proto::ThrowErrorRequest {
135                job_key: self.job_key,
136                error_code: self.error_code,
137                error_message: self.error_message,
138                variables: self.variables.to_string(),
139            })
140            .await?;
141
142        Ok(res.into_inner().into())
143    }
144}
145
146/// Empty response since throw error operation is fire-and-forget
147#[derive(Debug, Clone)]
148pub struct ThrowErrorResponse {}
149
150impl From<proto::ThrowErrorResponse> for ThrowErrorResponse {
151    fn from(_value: proto::ThrowErrorResponse) -> ThrowErrorResponse {
152        ThrowErrorResponse {}
153    }
154}