use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
use super::{
DeliveryAttempt, DeliveryExpiryCause, DeliveryFailureReason, HostActivationReceipt,
HostDeliveryId, HostDeliveryLease, HostDeliveryObservation, HostDeliveryStateKind,
ProcessedActionRef,
};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "state", rename_all = "snake_case")]
pub enum HostDeliveryState {
Queued,
Leased { lease: HostDeliveryLease },
DeliveredToHost { receipt: HostActivationReceipt },
Acknowledged {
observation: HostDeliveryObservation,
},
Processed {
#[serde(with = "time::serde::rfc3339")]
at: OffsetDateTime,
action: ProcessedActionRef,
},
Failed {
reason: DeliveryFailureReason,
attempt: DeliveryAttempt,
},
Expired {
#[serde(with = "time::serde::rfc3339")]
at: OffsetDateTime,
cause: DeliveryExpiryCause,
},
Superseded {
#[serde(default, skip_serializing_if = "Option::is_none")]
by: Option<HostDeliveryId>,
},
}
impl HostDeliveryState {
#[must_use]
pub const fn kind(&self) -> HostDeliveryStateKind {
match self {
Self::Queued => HostDeliveryStateKind::Queued,
Self::Leased { .. } => HostDeliveryStateKind::Leased,
Self::DeliveredToHost { .. } => HostDeliveryStateKind::DeliveredToHost,
Self::Acknowledged { .. } => HostDeliveryStateKind::Acknowledged,
Self::Processed { .. } => HostDeliveryStateKind::Processed,
Self::Failed { .. } => HostDeliveryStateKind::Failed,
Self::Expired { .. } => HostDeliveryStateKind::Expired,
Self::Superseded { .. } => HostDeliveryStateKind::Superseded,
}
}
#[must_use]
pub const fn is_terminal(&self) -> bool {
self.kind().is_terminal()
}
#[must_use]
pub const fn lease(&self) -> Option<&HostDeliveryLease> {
match self {
Self::Leased { lease } => Some(lease),
_ => None,
}
}
#[must_use]
pub const fn observation(&self) -> Option<&HostDeliveryObservation> {
match self {
Self::Acknowledged { observation } => Some(observation),
_ => None,
}
}
#[must_use]
pub const fn superseded_by(&self) -> Option<&HostDeliveryId> {
match self {
Self::Superseded { by } => by.as_ref(),
_ => None,
}
}
#[must_use]
pub const fn action(&self) -> Option<&ProcessedActionRef> {
match self {
Self::Processed { action, .. } => Some(action),
_ => None,
}
}
#[must_use]
pub const fn failure_reason(&self) -> Option<&DeliveryFailureReason> {
match self {
Self::Failed { reason, .. } => Some(reason),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_queued_delivery_carries_nothing_and_is_not_terminal() {
let state = HostDeliveryState::Queued;
assert_eq!(state.kind(), HostDeliveryStateKind::Queued);
assert!(!state.is_terminal());
assert!(state.lease().is_none());
assert!(state.observation().is_none());
assert!(state.action().is_none());
assert!(state.failure_reason().is_none());
}
}