use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
pub enum ShutdownPhase {
#[default]
Running,
DrainingListeners,
DrainingControlPlane,
DrainingDataPlane,
DrainingEventPlane,
PersistingWatermarks,
WalFsync,
Closed,
}
impl ShutdownPhase {
pub fn next(self) -> Option<Self> {
match self {
Self::Running => Some(Self::DrainingListeners),
Self::DrainingListeners => Some(Self::DrainingControlPlane),
Self::DrainingControlPlane => Some(Self::DrainingDataPlane),
Self::DrainingDataPlane => Some(Self::DrainingEventPlane),
Self::DrainingEventPlane => Some(Self::PersistingWatermarks),
Self::PersistingWatermarks => Some(Self::WalFsync),
Self::WalFsync => Some(Self::Closed),
Self::Closed => None,
}
}
pub fn label(self) -> &'static str {
match self {
Self::Running => "running",
Self::DrainingListeners => "draining_listeners",
Self::DrainingControlPlane => "draining_control_plane",
Self::DrainingDataPlane => "draining_data_plane",
Self::DrainingEventPlane => "draining_event_plane",
Self::PersistingWatermarks => "persisting_watermarks",
Self::WalFsync => "wal_fsync",
Self::Closed => "closed",
}
}
}
impl fmt::Display for ShutdownPhase {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.label())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn next_is_exhaustive_and_terminates() {
let mut phase = ShutdownPhase::Running;
let mut count = 0usize;
loop {
count += 1;
assert!(count < 20, "phase chain did not terminate");
match phase.next() {
Some(next) => phase = next,
None => {
assert_eq!(phase, ShutdownPhase::Closed);
break;
}
}
}
assert_eq!(count, 8);
}
#[test]
fn closed_has_no_next() {
assert_eq!(ShutdownPhase::Closed.next(), None);
}
#[test]
fn running_is_less_than_closed() {
assert!(ShutdownPhase::Running < ShutdownPhase::Closed);
assert!(ShutdownPhase::DrainingListeners < ShutdownPhase::WalFsync);
}
#[test]
fn labels_are_unique() {
use std::collections::HashSet;
let phases = [
ShutdownPhase::Running,
ShutdownPhase::DrainingListeners,
ShutdownPhase::DrainingControlPlane,
ShutdownPhase::DrainingDataPlane,
ShutdownPhase::DrainingEventPlane,
ShutdownPhase::PersistingWatermarks,
ShutdownPhase::WalFsync,
ShutdownPhase::Closed,
];
let labels: HashSet<_> = phases.iter().map(|p| p.label()).collect();
assert_eq!(labels.len(), phases.len());
}
}