Skip to main content

lxmf_sdk/types/
delivery.rs

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}