use serde::{Deserialize, Serialize};
use super::base::BaseEvent;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "event_type")]
pub enum DiscardEvent {
MessageDiscard {
#[serde(flatten)]
base: BaseEvent,
queue_id: String,
recipient: String,
relay: String,
delay: f64,
delays: DelayBreakdown,
dsn: String,
status: String,
discard_reason: String,
},
Configuration {
#[serde(flatten)]
base: BaseEvent,
config_type: DiscardConfigType,
details: String,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DelayBreakdown {
pub queue_wait: f64,
pub connection_setup: f64,
pub connection_time: f64,
pub transmission_time: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum DiscardConfigType {
TransportMapping,
DiscardRules,
ServiceStartup,
Other,
}
impl DiscardEvent {
pub fn queue_id(&self) -> Option<&str> {
match self {
DiscardEvent::MessageDiscard { queue_id, .. } => Some(queue_id),
DiscardEvent::Configuration { .. } => None,
}
}
pub fn recipient(&self) -> Option<&str> {
match self {
DiscardEvent::MessageDiscard { recipient, .. } => Some(recipient),
DiscardEvent::Configuration { .. } => None,
}
}
pub fn discard_reason(&self) -> Option<&str> {
match self {
DiscardEvent::MessageDiscard { discard_reason, .. } => Some(discard_reason),
DiscardEvent::Configuration { .. } => None,
}
}
pub fn is_message_discard(&self) -> bool {
matches!(self, DiscardEvent::MessageDiscard { .. })
}
pub fn severity(&self) -> &'static str {
match self {
DiscardEvent::MessageDiscard { .. } => "info", DiscardEvent::Configuration { .. } => "info", }
}
pub fn is_successful_discard(&self) -> bool {
match self {
DiscardEvent::MessageDiscard { status, dsn, .. } => {
status == "sent" && dsn.starts_with("2.") }
DiscardEvent::Configuration { .. } => false,
}
}
}
impl DelayBreakdown {
pub fn from_delays_string(delays_str: &str) -> Option<Self> {
let parts: Vec<&str> = delays_str.split('/').collect();
if parts.len() != 4 {
return None;
}
let queue_wait = parts[0].parse().ok()?;
let connection_setup = parts[1].parse().ok()?;
let connection_time = parts[2].parse().ok()?;
let transmission_time = parts[3].parse().ok()?;
Some(DelayBreakdown {
queue_wait,
connection_setup,
connection_time,
transmission_time,
})
}
pub fn total_delay(&self) -> f64 {
self.queue_wait + self.connection_setup + self.connection_time + self.transmission_time
}
pub fn is_fast_discard(&self) -> bool {
self.total_delay() < 0.1
}
}
impl std::fmt::Display for DiscardConfigType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DiscardConfigType::TransportMapping => write!(f, "transport mapping"),
DiscardConfigType::DiscardRules => write!(f, "discard rules"),
DiscardConfigType::ServiceStartup => write!(f, "service startup"),
DiscardConfigType::Other => write!(f, "other"),
}
}
}