zeebe_rs/decision.rs
1use crate::{Client, ClientError, proto};
2use serde::{Serialize, de::DeserializeOwned};
3
4pub struct Initial;
5pub struct WithKey;
6pub struct WithId;
7pub trait EvaluateDecisionRequestState {}
8impl EvaluateDecisionRequestState for Initial {}
9impl EvaluateDecisionRequestState for WithKey {}
10impl EvaluateDecisionRequestState for WithId {}
11
12/// Request to evaluate a DMN decision
13///
14/// The decision to evaluate can be specified either by using its unique key
15/// (as returned by DeployResource), or using the decision ID. When using the
16/// decision ID, the latest deployed version of the decision is used.
17///
18/// # Examples
19/// ```ignore
20/// client
21/// .evaluate_decision()
22/// .with_decision_key(123456)
23/// .with_decision_id(String::from("decision_id"))
24/// .send()
25/// .await?;
26/// ```
27#[derive(Debug, Clone)]
28pub struct EvaluateDecisionRequest<T: EvaluateDecisionRequestState> {
29 client: Client,
30 decision_key: i64,
31 decision_id: String,
32 variables: serde_json::Value,
33 tenant_id: String,
34 _state: std::marker::PhantomData<T>,
35}
36
37impl<T: EvaluateDecisionRequestState> EvaluateDecisionRequest<T> {
38 pub(crate) fn new(client: Client) -> EvaluateDecisionRequest<Initial> {
39 EvaluateDecisionRequest {
40 client,
41 decision_key: 0,
42 decision_id: String::new(),
43 variables: serde_json::Value::default(),
44 tenant_id: String::new(),
45 _state: std::marker::PhantomData,
46 }
47 }
48
49 fn transition<NewState: EvaluateDecisionRequestState>(
50 self,
51 ) -> EvaluateDecisionRequest<NewState> {
52 EvaluateDecisionRequest {
53 client: self.client,
54 decision_key: self.decision_key,
55 decision_id: self.decision_id,
56 variables: self.variables,
57 tenant_id: self.tenant_id,
58 _state: std::marker::PhantomData,
59 }
60 }
61}
62
63impl EvaluateDecisionRequest<Initial> {
64 /// Sets the unique key of the decision to evaluate
65 ///
66 /// # Arguments
67 /// * `decision_key` - The unique key identifying the decision (as returned by DeployResource)
68 ///
69 /// # Returns
70 /// The updated `EvaluateDecisionRequest` in the `WithKey` state.
71 pub fn with_decision_key(mut self, decision_key: i64) -> EvaluateDecisionRequest<WithKey> {
72 self.decision_key = decision_key;
73 self.transition()
74 }
75}
76
77impl EvaluateDecisionRequest<WithKey> {
78 /// Sets the ID of the decision to evaluate
79 ///
80 /// # Arguments
81 /// * `decision_id` - The ID of the decision to evaluate
82 ///
83 /// # Returns
84 /// The updated `EvaluateDecisionRequest` in the `WithId` state.
85 pub fn with_decision_id(mut self, decision_id: String) -> EvaluateDecisionRequest<WithId> {
86 self.decision_id = decision_id;
87 self.transition()
88 }
89}
90
91impl EvaluateDecisionRequest<WithId> {
92 /// Sets the variables used for decision evaluation
93 ///
94 /// The variables must be a JSON object, as variables will be mapped in a key-value fashion.
95 /// For example: `{ "a": 1, "b": 2 }` will create two variables named "a" and "b".
96 ///
97 /// # Arguments
98 /// * `data` - The variables to be used for decision evaluation
99 ///
100 /// # Returns
101 /// The updated `EvaluateDecisionRequest` with the variables set.
102 ///
103 /// # Errors
104 /// Returns a `ClientError` if the variables cannot be serialized to JSON.
105 pub fn with_variables<T: Serialize>(mut self, data: T) -> Result<Self, ClientError> {
106 self.variables = serde_json::to_value(data)
107 .map_err(|e| ClientError::SerializationFailed { source: e })?;
108 Ok(self)
109 }
110
111 /// Sends the decision evaluation request
112 ///
113 /// # Type Parameters
114 /// * `T` - The type of the decision output
115 ///
116 /// # Returns
117 /// A `Result` containing the `EvaluateDecisionResponse` or a `ClientError`.
118 pub async fn send<T: DeserializeOwned>(
119 mut self,
120 ) -> Result<EvaluateDecisionResponse<T>, ClientError> {
121 let res = self
122 .client
123 .gateway_client
124 .evaluate_decision(proto::EvaluateDecisionRequest {
125 decision_key: self.decision_key,
126 decision_id: self.decision_id,
127 variables: self.variables.to_string(),
128 tenant_id: self.tenant_id,
129 })
130 .await?;
131
132 res.into_inner().try_into()
133 }
134
135 /// Sets the tenant ID for the decision evaluation
136 ///
137 /// # Arguments
138 /// * `tenant_id` - The ID of the tenant that owns the decision
139 ///
140 /// # Returns
141 /// The updated `EvaluateDecisionRequest` with the tenant ID set.
142 pub fn with_tenant_id(mut self, tenant_id: String) -> Self {
143 self.tenant_id = tenant_id;
144 self
145 }
146}
147
148/// Represents an evaluated input in a decision
149#[derive(Debug, Clone)]
150pub struct EvaluatedDecisionInput {
151 input_id: String,
152 input_name: String,
153 input_value: String,
154}
155
156impl From<proto::EvaluatedDecisionInput> for EvaluatedDecisionInput {
157 fn from(value: proto::EvaluatedDecisionInput) -> EvaluatedDecisionInput {
158 EvaluatedDecisionInput {
159 input_id: value.input_id,
160 input_name: value.input_name,
161 input_value: value.input_value,
162 }
163 }
164}
165
166impl EvaluatedDecisionInput {
167 /// Returns the unique identifier of the evaluated input.
168 ///
169 /// # Returns
170 /// A string slice that holds the unique identifier of the evaluated input.
171 pub fn input_id(&self) -> &str {
172 &self.input_id
173 }
174
175 /// Returns the name/label of the evaluated input.
176 ///
177 /// # Returns
178 /// A string slice that holds the name/label of the evaluated input.
179 pub fn input_name(&self) -> &str {
180 &self.input_name
181 }
182
183 /// Returns the value of the input that was used during decision evaluation.
184 ///
185 /// # Returns
186 /// A string slice that holds the value of the input used during decision evaluation.
187 pub fn input_value(&self) -> &str {
188 &self.input_value
189 }
190}
191
192/// Represents an evaluated output in a decision
193#[derive(Debug, Clone)]
194pub struct EvaluatedDecisionOutput {
195 output_id: String,
196 output_name: String,
197 output_value: String,
198}
199
200impl From<proto::EvaluatedDecisionOutput> for EvaluatedDecisionOutput {
201 fn from(value: proto::EvaluatedDecisionOutput) -> EvaluatedDecisionOutput {
202 EvaluatedDecisionOutput {
203 output_id: value.output_id,
204 output_name: value.output_name,
205 output_value: value.output_value,
206 }
207 }
208}
209
210impl EvaluatedDecisionOutput {
211 /// Returns the unique identifier of the evaluated output
212 ///
213 /// # Returns
214 /// A string slice that holds the unique identifier of the evaluated output.
215 pub fn output_id(&self) -> &str {
216 &self.output_id
217 }
218
219 /// Returns the name/label of the evaluated output
220 ///
221 /// # Returns
222 /// A string slice that holds the name/label of the evaluated output.
223 pub fn output_name(&self) -> &str {
224 &self.output_name
225 }
226
227 /// Returns the value of the output that was used during decision evaluation
228 ///
229 /// # Returns
230 /// A string slice that holds the value of the output used during decision evaluation.
231 pub fn output_value(&self) -> &str {
232 &self.output_value
233 }
234}
235
236/// Represents a matched rule in a decision
237#[derive(Debug, Clone)]
238pub struct MatchedDecisionRule {
239 rule_id: String,
240 rule_index: i32,
241 evaluated_outputs: Vec<EvaluatedDecisionOutput>,
242}
243
244impl From<proto::MatchedDecisionRule> for MatchedDecisionRule {
245 fn from(value: proto::MatchedDecisionRule) -> MatchedDecisionRule {
246 MatchedDecisionRule {
247 rule_id: value.rule_id,
248 rule_index: value.rule_index,
249 evaluated_outputs: value
250 .evaluated_outputs
251 .into_iter()
252 .map(|e| e.into())
253 .collect(),
254 }
255 }
256}
257
258impl MatchedDecisionRule {
259 /// Returns the unique identifier of the matched rule.
260 ///
261 /// # Returns
262 /// A string slice that holds the unique identifier of the matched rule.
263 pub fn rule_id(&self) -> &str {
264 &self.rule_id
265 }
266
267 /// Returns the index position of the matched rule within the decision table.
268 ///
269 /// # Returns
270 /// An integer representing the index position of the matched rule.
271 pub fn rule_index(&self) -> i32 {
272 self.rule_index
273 }
274
275 /// Returns a slice containing all evaluated outputs for this matched rule.
276 ///
277 /// # Returns
278 /// A slice of `EvaluatedDecisionOutput` containing all evaluated outputs for this matched rule.
279 pub fn evaluated_outputs(&self) -> &[EvaluatedDecisionOutput] {
280 &self.evaluated_outputs
281 }
282}
283
284/// Represents an evaluated decision
285#[derive(Debug, Clone)]
286pub struct EvaluatedDecision {
287 decision_key: i64,
288 decision_id: String,
289 decision_name: String,
290 decision_version: i32,
291 decision_type: String,
292 decision_output: String,
293 matched_rules: Vec<MatchedDecisionRule>,
294 evaluated_inputs: Vec<EvaluatedDecisionInput>,
295 tenant_id: String,
296}
297
298impl From<proto::EvaluatedDecision> for EvaluatedDecision {
299 fn from(value: proto::EvaluatedDecision) -> EvaluatedDecision {
300 EvaluatedDecision {
301 decision_key: value.decision_key,
302 decision_id: value.decision_id,
303 decision_name: value.decision_name,
304 decision_version: value.decision_version,
305 decision_type: value.decision_type,
306 decision_output: value.decision_output,
307 matched_rules: value.matched_rules.into_iter().map(|m| m.into()).collect(),
308 evaluated_inputs: value
309 .evaluated_inputs
310 .into_iter()
311 .map(|e| e.into())
312 .collect(),
313 tenant_id: value.tenant_id,
314 }
315 }
316}
317
318impl EvaluatedDecision {
319 /// Returns the unique key identifying the evaluated decision
320 ///
321 /// # Returns
322 ///
323 /// An `i64` representing the unique key of the evaluated decision
324 pub fn decision_key(&self) -> i64 {
325 self.decision_key
326 }
327
328 /// Returns the ID of the decision which was evaluated
329 ///
330 /// # Returns
331 ///
332 /// A string slice (`&str`) representing the ID of the evaluated decision
333 pub fn decision_id(&self) -> &str {
334 &self.decision_id
335 }
336
337 /// Returns the name of the decision which was evaluated
338 ///
339 /// # Returns
340 ///
341 /// A string slice (`&str`) representing the name of the evaluated decision
342 pub fn decision_name(&self) -> &str {
343 &self.decision_name
344 }
345
346 /// Returns the version of the decision which was evaluated
347 ///
348 /// # Returns
349 ///
350 /// An `i32` representing the version of the evaluated decision
351 pub fn decision_version(&self) -> i32 {
352 self.decision_version
353 }
354
355 /// Returns the type of the decision which was evaluated
356 ///
357 /// # Returns
358 ///
359 /// A string slice (`&str`) representing the type of the evaluated decision
360 pub fn decision_type(&self) -> &str {
361 &self.decision_type
362 }
363
364 /// Returns the JSON output of the evaluated decision
365 ///
366 /// The output is a JSON-formatted string representing the decision result
367 ///
368 /// # Returns
369 pub fn decision_output(&self) -> &str {
370 &self.decision_output
371 }
372
373 /// A string slice (`&str`) representing the JSON output of the evaluated decision
374 ///
375 /// Returns a slice containing all rules that matched during decision evaluation
376 ///
377 /// # Returns
378 ///
379 /// A slice (`&[MatchedDecisionRule]`) containing all matched rules
380 pub fn matched_rules(&self) -> &[MatchedDecisionRule] {
381 &self.matched_rules
382 }
383
384 /// Returns a slice containing all inputs that were evaluated as part of the decision
385 ///
386 /// # Returns
387 ///
388 /// A slice (`&[EvaluatedDecisionInput]`) containing all evaluated inputs
389 pub fn evaluated_inputs(&self) -> &[EvaluatedDecisionInput] {
390 &self.evaluated_inputs
391 }
392
393 /// Returns the tenant identifier of the evaluated decision
394 ///
395 /// # Returns
396 ///
397 /// A string slice (`&str`) representing the tenant identifier of the evaluated decision
398 pub fn tenant_id(&self) -> &str {
399 &self.tenant_id
400 }
401}
402
403/// The response from evaluating a decision
404#[derive(Debug, Clone)]
405pub struct EvaluateDecisionResponse<T: DeserializeOwned> {
406 decision_key: i64,
407 decision_id: String,
408 decision_name: String,
409 decision_version: i32,
410 decision_requirements_id: String,
411 decision_requirements_key: i64,
412 decision_output: T,
413 evaluated_decisions: Vec<EvaluatedDecision>,
414 failed_decision_id: String,
415 failure_message: String,
416 tenant_id: String,
417 decision_instance_key: i64,
418}
419
420impl<T: DeserializeOwned> TryFrom<proto::EvaluateDecisionResponse> for EvaluateDecisionResponse<T> {
421 type Error = ClientError;
422 fn try_from(
423 value: proto::EvaluateDecisionResponse,
424 ) -> Result<EvaluateDecisionResponse<T>, Self::Error> {
425 Ok(EvaluateDecisionResponse {
426 decision_key: value.decision_key,
427 decision_id: value.decision_id,
428 decision_name: value.decision_name,
429 decision_version: value.decision_version,
430 decision_requirements_id: value.decision_requirements_id,
431 decision_requirements_key: value.decision_requirements_key,
432 decision_output: serde_json::from_str(&value.decision_output).map_err(|e| {
433 ClientError::DeserializationFailed {
434 value: value.decision_output.clone(),
435 source: e,
436 }
437 })?,
438 evaluated_decisions: value
439 .evaluated_decisions
440 .into_iter()
441 .map(|e| e.into())
442 .collect(),
443 failed_decision_id: value.failed_decision_id,
444 failure_message: value.failure_message,
445 tenant_id: value.tenant_id,
446 decision_instance_key: value.decision_instance_key,
447 })
448 }
449}
450
451/// Represents the response of evaluating a decision, parameterized by the type `T`.
452///
453/// This struct provides various methods to access details about the evaluated decision,
454/// including its key, ID, name, version, and output, as well as information about any
455/// failures that occurred during the evaluation.
456impl<T: DeserializeOwned> EvaluateDecisionResponse<T> {
457 /// Returns the unique key identifying the evaluated decision.
458 ///
459 /// # Returns
460 ///
461 /// An `i64` representing the unique key of the decision.
462 pub fn decision_key(&self) -> i64 {
463 self.decision_key
464 }
465
466 /// Returns the ID of the decision which was evaluated.
467 ///
468 /// # Returns
469 ///
470 /// A string slice representing the ID of the evaluated decision.
471 pub fn decision_id(&self) -> &str {
472 &self.decision_id
473 }
474
475 /// Returns the name of the decision which was evaluated.
476 ///
477 /// # Returns
478 ///
479 /// A string slice representing the name of the evaluated decision.
480 pub fn decision_name(&self) -> &str {
481 &self.decision_name
482 }
483
484 /// Returns the version of the decision which was evaluated.
485 ///
486 /// # Returns
487 ///
488 /// An `i32` representing the version of the evaluated decision.
489 pub fn decision_version(&self) -> i32 {
490 self.decision_version
491 }
492
493 /// Returns the ID of the decision requirements graph that the decision is part of.
494 ///
495 /// # Returns
496 ///
497 /// A string slice representing the ID of the decision requirements graph.
498 pub fn decision_requirements_id(&self) -> &str {
499 &self.decision_requirements_id
500 }
501
502 /// Returns the unique key identifying the decision requirements graph.
503 ///
504 /// # Returns
505 ///
506 /// An `i64` representing the unique key of the decision requirements graph.
507 pub fn decision_requirements_key(&self) -> i64 {
508 self.decision_requirements_key
509 }
510
511 /// Returns the output result of the decision evaluation.
512 ///
513 /// # Returns
514 ///
515 /// A reference to the output of the decision evaluation of type `T`.
516 pub fn decision_output(&self) -> &T {
517 &self.decision_output
518 }
519
520 /// Returns a list of all decisions that were evaluated within the requested decision evaluation.
521 ///
522 /// # Returns
523 ///
524 /// A slice of `EvaluatedDecision` representing all evaluated decisions.
525 pub fn evaluated_decisions(&self) -> &[EvaluatedDecision] {
526 &self.evaluated_decisions
527 }
528
529 /// Returns the ID of the decision which failed during evaluation, if any.
530 ///
531 /// # Returns
532 ///
533 /// A string slice representing the ID of the failed decision, if applicable.
534 pub fn failed_decision_id(&self) -> &str {
535 &self.failed_decision_id
536 }
537
538 /// Returns a message describing why the decision evaluation failed, if applicable.
539 ///
540 /// # Returns
541 ///
542 /// A string slice representing the failure message, if applicable.
543 pub fn failure_message(&self) -> &str {
544 &self.failure_message
545 }
546
547 /// Returns the tenant identifier of the evaluated decision.
548 ///
549 /// # Returns
550 ///
551 /// A string slice representing the tenant ID of the evaluated decision.
552 pub fn tenant_id(&self) -> &str {
553 &self.tenant_id
554 }
555
556 /// Returns the unique key identifying this decision evaluation.
557 ///
558 /// # Returns
559 ///
560 /// An `i64` representing the unique key of this decision evaluation.
561 pub fn decision_instance_key(&self) -> i64 {
562 self.decision_instance_key
563 }
564}