puerto_core/events/
handler.rs1use async_trait::async_trait;
2
3use super::EventEnvelope;
4
5pub const REASON_PAYLOAD_INVALID: &str = "payload_invalid";
7pub const REASON_MAX_DELIVERIES_EXCEEDED: &str = "max_deliveries_exceeded";
9pub const REASON_PERMANENT_ERROR: &str = "permanent_error";
11
12#[async_trait]
15pub trait EventHandler: Send + Sync {
16 async fn handle(&self, event: &EventEnvelope) -> HandlerOutcome;
17}
18
19#[non_exhaustive]
22#[derive(Debug, Clone, PartialEq, Eq)]
23pub enum HandlerOutcome {
24 Ack,
26 Retry,
28 DeadLetter {
30 reason: &'static str,
32 detail: String,
33 },
34}
35
36impl HandlerOutcome {
37 pub fn dead_letter(reason: &'static str, detail: impl Into<String>) -> Self {
38 Self::DeadLetter {
39 reason,
40 detail: detail.into(),
41 }
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[test]
50 fn should_keep_reason_codes_stable_when_stored_in_dead_letters() {
51 assert_eq!(REASON_PAYLOAD_INVALID, "payload_invalid");
52 assert_eq!(REASON_MAX_DELIVERIES_EXCEEDED, "max_deliveries_exceeded");
53 assert_eq!(REASON_PERMANENT_ERROR, "permanent_error");
54 }
55
56 #[test]
57 fn should_carry_reason_and_detail_when_dead_lettered() {
58 assert_eq!(
59 HandlerOutcome::dead_letter(REASON_PERMANENT_ERROR, "card declined"),
60 HandlerOutcome::DeadLetter {
61 reason: "permanent_error",
62 detail: "card declined".into()
63 }
64 );
65 }
66}