1use serde::{Deserialize, Serialize};
2use serde_json::Value as JsonValue;
3use std::collections::BTreeMap;
4use std::fmt::{Display, Formatter};
5
6#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
7#[non_exhaustive]
8pub struct SendRequest {
9 pub source: String,
10 pub destination: String,
11 pub payload: JsonValue,
12 #[serde(default)]
13 pub delivery_method: Option<String>,
14 #[serde(default)]
15 pub stamp_cost: Option<u32>,
16 #[serde(default)]
17 pub include_ticket: Option<bool>,
18 #[serde(default)]
19 pub try_propagation_on_fail: Option<bool>,
20 pub idempotency_key: Option<String>,
21 pub ttl_ms: Option<u64>,
22 pub correlation_id: Option<String>,
23 #[serde(default)]
24 pub extensions: BTreeMap<String, JsonValue>,
25}
26
27impl SendRequest {
28 pub fn new(
29 source: impl Into<String>,
30 destination: impl Into<String>,
31 payload: JsonValue,
32 ) -> Self {
33 Self {
34 source: source.into(),
35 destination: destination.into(),
36 payload,
37 delivery_method: None,
38 stamp_cost: None,
39 include_ticket: None,
40 try_propagation_on_fail: None,
41 idempotency_key: None,
42 ttl_ms: None,
43 correlation_id: None,
44 extensions: BTreeMap::new(),
45 }
46 }
47
48 pub fn with_idempotency_key(mut self, key: impl Into<String>) -> Self {
49 self.idempotency_key = Some(key.into());
50 self
51 }
52
53 pub fn with_ttl_ms(mut self, ttl_ms: u64) -> Self {
54 self.ttl_ms = Some(ttl_ms);
55 self
56 }
57
58 pub fn with_correlation_id(mut self, correlation_id: impl Into<String>) -> Self {
59 self.correlation_id = Some(correlation_id.into());
60 self
61 }
62
63 pub fn with_delivery_method(mut self, method: impl Into<String>) -> Self {
64 self.delivery_method = Some(method.into());
65 self
66 }
67
68 pub fn with_stamp_cost(mut self, stamp_cost: u32) -> Self {
69 self.stamp_cost = Some(stamp_cost);
70 self
71 }
72
73 pub fn with_include_ticket(mut self, include_ticket: bool) -> Self {
74 self.include_ticket = Some(include_ticket);
75 self
76 }
77
78 pub fn with_try_propagation_on_fail(mut self, try_propagation_on_fail: bool) -> Self {
79 self.try_propagation_on_fail = Some(try_propagation_on_fail);
80 self
81 }
82
83 pub fn with_extension(mut self, key: impl Into<String>, value: JsonValue) -> Self {
84 self.extensions.insert(key.into(), value);
85 self
86 }
87}
88
89#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
90#[non_exhaustive]
91pub struct GroupSendRequest {
92 pub source: String,
93 pub destinations: Vec<String>,
94 pub payload: JsonValue,
95 pub idempotency_key: Option<String>,
96 pub ttl_ms: Option<u64>,
97 pub correlation_id: Option<String>,
98 #[serde(default)]
99 pub extensions: BTreeMap<String, JsonValue>,
100}
101
102impl GroupSendRequest {
103 pub fn new(
104 source: impl Into<String>,
105 destinations: impl IntoIterator<Item = impl Into<String>>,
106 payload: JsonValue,
107 ) -> Self {
108 Self {
109 source: source.into(),
110 destinations: destinations.into_iter().map(Into::into).collect(),
111 payload,
112 idempotency_key: None,
113 ttl_ms: None,
114 correlation_id: None,
115 extensions: BTreeMap::new(),
116 }
117 }
118
119 pub fn with_idempotency_key(mut self, key: impl Into<String>) -> Self {
120 self.idempotency_key = Some(key.into());
121 self
122 }
123
124 pub fn with_ttl_ms(mut self, ttl_ms: u64) -> Self {
125 self.ttl_ms = Some(ttl_ms);
126 self
127 }
128
129 pub fn with_correlation_id(mut self, correlation_id: impl Into<String>) -> Self {
130 self.correlation_id = Some(correlation_id.into());
131 self
132 }
133
134 pub fn with_extension(mut self, key: impl Into<String>, value: JsonValue) -> Self {
135 self.extensions.insert(key.into(), value);
136 self
137 }
138}
139
140#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
141#[serde(rename_all = "snake_case")]
142#[non_exhaustive]
143pub enum GroupRecipientState {
144 Accepted,
145 Deferred,
146 Failed,
147}
148
149#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
150#[non_exhaustive]
151pub struct GroupSendOutcome {
152 pub destination: String,
153 pub state: GroupRecipientState,
154 pub message_id: Option<MessageId>,
155 pub retryable: bool,
156 pub reason_code: Option<String>,
157}
158
159#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
160#[non_exhaustive]
161pub struct GroupSendResult {
162 pub outcomes: Vec<GroupSendOutcome>,
163 pub accepted_count: usize,
164 pub deferred_count: usize,
165 pub failed_count: usize,
166}
167
168#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
169#[non_exhaustive]
170pub struct BatchSendRequest {
171 pub batch_id: String,
172 pub source: String,
173 pub messages: Vec<BatchSendItem>,
174}
175
176#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
177#[non_exhaustive]
178pub struct BatchSendItem {
179 pub id: String,
180 pub destination: String,
181 pub payload: JsonValue,
182 #[serde(default)]
183 pub delivery_method: Option<String>,
184 #[serde(default)]
185 pub stamp_cost: Option<u32>,
186 #[serde(default)]
187 pub include_ticket: Option<bool>,
188 #[serde(default)]
189 pub try_propagation_on_fail: Option<bool>,
190 pub idempotency_key: Option<String>,
191 pub ttl_ms: Option<u64>,
192 pub correlation_id: Option<String>,
193 #[serde(default)]
194 pub extensions: BTreeMap<String, JsonValue>,
195}
196
197impl BatchSendItem {
198 pub fn new(id: impl Into<String>, destination: impl Into<String>, payload: JsonValue) -> Self {
199 Self {
200 id: id.into(),
201 destination: destination.into(),
202 payload,
203 delivery_method: None,
204 stamp_cost: None,
205 include_ticket: None,
206 try_propagation_on_fail: None,
207 idempotency_key: None,
208 ttl_ms: None,
209 correlation_id: None,
210 extensions: BTreeMap::new(),
211 }
212 }
213
214 pub fn with_idempotency_key(mut self, key: impl Into<String>) -> Self {
215 self.idempotency_key = Some(key.into());
216 self
217 }
218
219 pub fn with_ttl_ms(mut self, ttl_ms: u64) -> Self {
220 self.ttl_ms = Some(ttl_ms);
221 self
222 }
223
224 pub fn with_correlation_id(mut self, correlation_id: impl Into<String>) -> Self {
225 self.correlation_id = Some(correlation_id.into());
226 self
227 }
228
229 pub fn with_extension(mut self, key: impl Into<String>, value: JsonValue) -> Self {
230 self.extensions.insert(key.into(), value);
231 self
232 }
233
234 pub fn with_delivery_method(mut self, method: impl Into<String>) -> Self {
235 self.delivery_method = Some(method.into());
236 self
237 }
238
239 pub fn with_stamp_cost(mut self, stamp_cost: u32) -> Self {
240 self.stamp_cost = Some(stamp_cost);
241 self
242 }
243
244 pub fn with_include_ticket(mut self, include_ticket: bool) -> Self {
245 self.include_ticket = Some(include_ticket);
246 self
247 }
248
249 pub fn with_try_propagation_on_fail(mut self, try_propagation_on_fail: bool) -> Self {
250 self.try_propagation_on_fail = Some(try_propagation_on_fail);
251 self
252 }
253}
254
255#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
256#[non_exhaustive]
257pub struct BatchSendResult {
258 pub batch_id: String,
259 pub accepted_count: usize,
260 pub rejected_count: usize,
261 pub results: Vec<BatchSendItemResult>,
262}
263
264#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
265#[non_exhaustive]
266pub struct BatchSendItemResult {
267 pub id: String,
268 #[serde(default)]
269 pub message_id: Option<String>,
270 pub accepted: bool,
271 #[serde(default)]
272 pub error: Option<BatchSendItemError>,
273}
274
275#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
276#[non_exhaustive]
277pub struct BatchSendItemError {
278 pub code: String,
279 #[serde(default)]
280 pub message: String,
281 #[serde(default)]
282 pub category: Option<String>,
283 #[serde(default)]
284 pub retryable: bool,
285}
286
287#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
288pub struct MessageId(pub String);
289
290impl From<String> for MessageId {
291 fn from(value: String) -> Self {
292 Self(value)
293 }
294}
295
296impl From<&str> for MessageId {
297 fn from(value: &str) -> Self {
298 Self(value.to_owned())
299 }
300}
301
302impl Display for MessageId {
303 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
304 f.write_str(self.0.as_str())
305 }
306}
307
308#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
309#[serde(rename_all = "snake_case")]
310#[non_exhaustive]
311pub enum DeliveryState {
312 Queued,
313 Dispatching,
314 InFlight,
315 Sent,
316 Delivered,
317 Failed,
318 Cancelled,
319 Expired,
320 Rejected,
321 #[serde(other)]
322 Unknown,
323}
324
325#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
326#[non_exhaustive]
327pub struct DeliverySnapshot {
328 pub message_id: MessageId,
329 pub state: DeliveryState,
330 pub terminal: bool,
331 pub last_updated_ms: u64,
332 pub attempts: u32,
333 pub reason_code: Option<String>,
334}
335
336#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
337#[non_exhaustive]
338pub struct Ack {
339 pub accepted: bool,
340 pub revision: Option<u64>,
341}
342
343#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
344#[serde(rename_all = "snake_case")]
345#[non_exhaustive]
346pub enum CancelResult {
347 Accepted,
348 AlreadyTerminal,
349 NotFound,
350 TooLateToCancel,
351 Unsupported,
352}