use async_trait::async_trait;
use super::EventEnvelope;
pub const REASON_PAYLOAD_INVALID: &str = "payload_invalid";
pub const REASON_MAX_DELIVERIES_EXCEEDED: &str = "max_deliveries_exceeded";
pub const REASON_PERMANENT_ERROR: &str = "permanent_error";
#[async_trait]
pub trait EventHandler: Send + Sync {
async fn handle(&self, event: &EventEnvelope) -> HandlerOutcome;
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum HandlerOutcome {
Ack,
Retry,
DeadLetter {
reason: &'static str,
detail: String,
},
}
impl HandlerOutcome {
pub fn dead_letter(reason: &'static str, detail: impl Into<String>) -> Self {
Self::DeadLetter {
reason,
detail: detail.into(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn should_keep_reason_codes_stable_when_stored_in_dead_letters() {
assert_eq!(REASON_PAYLOAD_INVALID, "payload_invalid");
assert_eq!(REASON_MAX_DELIVERIES_EXCEEDED, "max_deliveries_exceeded");
assert_eq!(REASON_PERMANENT_ERROR, "permanent_error");
}
#[test]
fn should_carry_reason_and_detail_when_dead_lettered() {
assert_eq!(
HandlerOutcome::dead_letter(REASON_PERMANENT_ERROR, "card declined"),
HandlerOutcome::DeadLetter {
reason: "permanent_error",
detail: "card declined".into()
}
);
}
}