zeebe_rs/signal.rs
1use crate::{Client, ClientError, proto};
2use serde::Serialize;
3
4pub struct Initial;
5pub struct WithName;
6
7pub trait BroadcastSignalRequestState {}
8impl BroadcastSignalRequestState for Initial {}
9impl BroadcastSignalRequestState for WithName {}
10
11/// Request to broadcast a signal across the cluster
12///
13/// A signal can trigger multiple catching signal events in different process instances.
14/// Signal events are matched by name and tenant ID if multi-tenancy is enabled.
15///
16/// # Examples
17/// ```ignore
18/// client
19/// .broadcast_signal()
20/// .with_signal_name(String::from("Hello_Signal"))
21/// .send()
22/// .await?;
23/// ```
24#[derive(Debug, Clone)]
25pub struct BroadcastSignalRequest<T: BroadcastSignalRequestState> {
26 client: Client,
27 signal_name: String,
28 variables: serde_json::Value,
29 tenant_id: String,
30 _state: std::marker::PhantomData<T>,
31}
32
33impl<T: BroadcastSignalRequestState> BroadcastSignalRequest<T> {
34 pub(crate) fn new(client: Client) -> BroadcastSignalRequest<Initial> {
35 BroadcastSignalRequest {
36 client,
37 signal_name: String::new(),
38 variables: serde_json::Value::default(),
39 tenant_id: String::new(),
40 _state: std::marker::PhantomData,
41 }
42 }
43
44 fn transition<NewState: BroadcastSignalRequestState>(self) -> BroadcastSignalRequest<NewState> {
45 BroadcastSignalRequest {
46 client: self.client,
47 signal_name: self.signal_name,
48 variables: self.variables,
49 tenant_id: self.tenant_id,
50 _state: std::marker::PhantomData,
51 }
52 }
53}
54
55impl BroadcastSignalRequest<Initial> {
56 /// Sets the name of the signal to broadcast
57 ///
58 /// # Arguments
59 /// * `signal_name` - Name that will be matched with signal catch events
60 ///
61 /// # Returns
62 /// A `BroadcastSignalRequest` in the `WithName` state
63 pub fn with_signal_name(mut self, signal_name: String) -> BroadcastSignalRequest<WithName> {
64 self.signal_name = signal_name;
65 self.transition()
66 }
67}
68
69impl BroadcastSignalRequest<WithName> {
70 /// Sets variables that will be available to all triggered signal events
71 ///
72 /// # Arguments
73 /// * `data` - Variables as serializable type that will be converted to JSON
74 ///
75 /// # Returns
76 /// A `Result` containing the updated `BroadcastSignalRequest` or a `ClientError`
77 ///
78 /// # Notes
79 /// Must be a JSON object, e.g. `{ "a": 1, "b": 2 }`. Arrays like `[1, 2]` are not valid.
80 pub fn with_variables<T: Serialize>(mut self, data: T) -> Result<Self, ClientError> {
81 self.variables = serde_json::to_value(data)
82 .map_err(|e| ClientError::SerializationFailed { source: e })?;
83 Ok(self)
84 }
85
86 /// Sets the tenant ID that owns this signal
87 ///
88 /// # Arguments
89 /// * `tenant_id` - ID of tenant that owns the signal
90 ///
91 /// # Returns
92 /// The updated `BroadcastSignalRequest`
93 pub fn with_tenant_id(mut self, tenant_id: String) -> Self {
94 self.tenant_id = tenant_id;
95 self
96 }
97
98 /// Sends the broadcast signal request to the gateway
99 ///
100 /// # Returns
101 /// A `Result` containing the `BroadcastSignalResponse` or a `ClientError`
102 ///
103 /// # Errors
104 /// - `INVALID_ARGUMENT`: Missing signal name or invalid variables format
105 /// - `PERMISSION_DENIED`: Not authorized for tenant
106 pub async fn send(mut self) -> Result<BroadcastSignalResponse, ClientError> {
107 let res = self
108 .client
109 .gateway_client
110 .broadcast_signal(proto::BroadcastSignalRequest {
111 signal_name: self.signal_name,
112 variables: self.variables.to_string(),
113 tenant_id: self.tenant_id,
114 })
115 .await?;
116
117 Ok(res.into_inner().into())
118 }
119}
120
121/// Response from broadcasting a signal
122///
123/// Contains:
124/// - Key uniquely identifying this signal broadcast
125/// - Tenant ID that owns the signal
126#[derive(Debug, Clone)]
127pub struct BroadcastSignalResponse {
128 key: i64,
129 tenant_id: String,
130}
131
132impl From<proto::BroadcastSignalResponse> for BroadcastSignalResponse {
133 fn from(value: proto::BroadcastSignalResponse) -> BroadcastSignalResponse {
134 BroadcastSignalResponse {
135 key: value.key,
136 tenant_id: value.tenant_id,
137 }
138 }
139}
140
141impl BroadcastSignalResponse {
142 /// Returns the unique identifier for this signal broadcast operation
143 ///
144 /// # Returns
145 /// The unique identifier for this signal broadcast operation
146 pub fn key(&self) -> i64 {
147 self.key
148 }
149
150 /// Returns the ID of tenant that owns the signal
151 ///
152 /// # Returns
153 /// The ID of tenant that owns the signal, empty if multi-tenancy is disabled
154 pub fn tenant_id(&self) -> &str {
155 &self.tenant_id
156 }
157}