use std::any::Any;
use crate::core::ChildName;
use crate::internal::ProcessOutcome;
#[derive(Debug)]
pub enum Escalation {
Startup(StartupFailure),
TooManyRestarts(RestartReason),
Unknown(Box<dyn Any + Send>),
}
#[derive(Debug)]
pub enum StartupFailure {
ReusedKey(ChildName),
ChildFailure(ChildName, Box<dyn Any + Send>),
Interrupted,
NonChildFailure(Box<dyn Any + Send>),
}
impl StartupFailure {
pub fn message(&self) -> String {
match self {
StartupFailure::ReusedKey(name) => format!("Key was reused for child {}", name.to_string()),
StartupFailure::ChildFailure(name, fail) => {
let reason = if let Some(m) = fail.downcast_ref::<&str>() {
m.to_string()
} else if let Some(m) = fail.downcast_ref::<String>() {
m.clone()
} else if let Some(m) = fail.downcast_ref::<Escalation>() {
format!("{:?}", m)
} else {
String::from("unknown")
};
format!("Child {} failed to start: {}", name.to_string(), reason)
}
StartupFailure::Interrupted => String::from("Settlement interrupted"),
StartupFailure::NonChildFailure(x) => {
if let Some(m) = x.downcast_ref::<&str>() {
m.to_string()
} else if let Some(m) = x.downcast_ref::<String>() {
m.clone()
} else if let Some(m) = x.downcast_ref::<Escalation>() {
format!("{:?}", m)
} else {
String::from("unknown")
}
}
}
}
}
#[derive(Debug)]
pub enum RestartReason {
PermanentChildTerminated(ChildName, TerminationReason),
TransientChildFailed(ChildName, Box<dyn Any + Send>),
RestartFailure(StartupFailure),
}
#[derive(Debug)]
pub enum TerminationReason {
Normal,
Aborted,
Panicked(Box<dyn Any + Send>),
}
impl TerminationReason {
pub(crate) fn as_outcome(&self) -> ProcessOutcome {
match self {
TerminationReason::Normal => ProcessOutcome::Normal,
TerminationReason::Aborted => ProcessOutcome::Aborted,
TerminationReason::Panicked(_) => ProcessOutcome::Panicked,
}
}
}