use crate::relay::{ListedBundle, ListedBundleStartupHealth, ListedBundleState};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BundleStatusDisplay {
pub bundle_name: String,
pub hosted: bool,
pub state: ListedBundleState,
pub startup_health: Option<ListedBundleStartupHealth>,
pub state_reason_code: Option<String>,
pub startup_failure_count: usize,
}
impl BundleStatusDisplay {
pub fn from_listed_bundle(bundle: &ListedBundle) -> Self {
Self {
bundle_name: bundle.id.clone(),
hosted: bundle.hosted,
state: bundle.state.clone(),
startup_health: bundle.startup_health.clone(),
state_reason_code: bundle.state_reason_code.clone(),
startup_failure_count: bundle.startup_failure_count,
}
}
}
pub fn format_bundle_status_line(status: &BundleStatusDisplay) -> String {
let hosted_token = if status.hosted { "yes" } else { "no" };
let state_token = listed_bundle_state_token(&status.state);
let mut parts = vec![
format!("bundle={}", status.bundle_name),
format!("hosted={hosted_token}"),
format!("state={state_token}"),
];
if let Some(health) = status.startup_health.as_ref() {
parts.push(format!(
"startup_health={}",
listed_bundle_startup_health_token(health)
));
}
if let Some(reason_code) = status.state_reason_code.as_ref() {
parts.push(format!("reason_code={reason_code}"));
}
if status.startup_failure_count > 0 {
parts.push(format!(
"startup_failure_count={}",
status.startup_failure_count
));
}
parts.join(" ")
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum BundleStatusSeverity {
Healthy,
Degraded,
HostedDown,
Unhosted,
}
pub fn bundle_status_severity(status: &BundleStatusDisplay) -> BundleStatusSeverity {
match (status.hosted, &status.state) {
(true, ListedBundleState::Up) => match status.startup_health {
Some(ListedBundleStartupHealth::Healthy) => BundleStatusSeverity::Healthy,
_ => BundleStatusSeverity::Degraded,
},
(true, ListedBundleState::Down) => BundleStatusSeverity::HostedDown,
(false, _) => BundleStatusSeverity::Unhosted,
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RecipientReadiness {
Ready,
NotReady,
}
impl RecipientReadiness {
pub fn from_ready(ready: bool) -> Self {
if ready { Self::Ready } else { Self::NotReady }
}
}
pub fn format_recipient_picker_label(
session_name: &str,
display_name: Option<&str>,
readiness: RecipientReadiness,
) -> String {
let base = match display_name {
Some(name) => format!("{session_name} ({name})"),
None => session_name.to_string(),
};
match readiness {
RecipientReadiness::Ready => base,
RecipientReadiness::NotReady => format!("{base} [not ready]"),
}
}
fn listed_bundle_state_token(state: &ListedBundleState) -> &'static str {
match state {
ListedBundleState::Up => "up",
ListedBundleState::Down => "down",
}
}
fn listed_bundle_startup_health_token(health: &ListedBundleStartupHealth) -> &'static str {
match health {
ListedBundleStartupHealth::Healthy => "healthy",
ListedBundleStartupHealth::Degraded => "degraded",
}
}