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}