use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ExternalEffectSettlement {
NotStarted,
Running,
Succeeded,
Failed,
InterruptedUnknown,
}
impl ExternalEffectSettlement {
pub fn may_have_executed(self) -> bool {
matches!(
self,
Self::Running | Self::Succeeded | Self::Failed | Self::InterruptedUnknown
)
}
pub fn allows_automatic_non_idempotent_replay(self) -> bool {
matches!(self, Self::NotStarted)
}
pub fn requires_reconciliation(self) -> bool {
matches!(self, Self::InterruptedUnknown)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn interrupted_unknown_is_never_blindly_replayed() {
let state = ExternalEffectSettlement::InterruptedUnknown;
assert!(state.may_have_executed());
assert!(state.requires_reconciliation());
assert!(!state.allows_automatic_non_idempotent_replay());
}
#[test]
fn only_known_not_started_is_default_replay_safe() {
for state in [
ExternalEffectSettlement::Running,
ExternalEffectSettlement::Succeeded,
ExternalEffectSettlement::Failed,
ExternalEffectSettlement::InterruptedUnknown,
] {
assert!(!state.allows_automatic_non_idempotent_replay());
}
assert!(ExternalEffectSettlement::NotStarted.allows_automatic_non_idempotent_replay());
}
}