use liminal::channel::ChannelMode;
use crate::ServerError;
use crate::server::connection::channel_registry::{ChannelOrigin, ChannelStatus};
use crate::server::connection::services::LiminalConnectionServices;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ChannelNode {
pub name: String,
pub mode: &'static str,
pub state: &'static str,
pub origin: &'static str,
pub reason: Option<String>,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct TopologySnapshot {
pub channels: Vec<ChannelNode>,
pub services: Vec<String>,
}
pub fn snapshot(services: &LiminalConnectionServices) -> Result<TopologySnapshot, ServerError> {
let roster_error = |error: &dyn std::fmt::Display| ServerError::ListenerAccept {
message: format!("console topology: {error}"),
};
let census = services
.channel_census()
.map_err(|error| roster_error(&error))?;
let mut channels = Vec::with_capacity(census.len());
for (name, status) in census {
let node = match status {
ChannelStatus::NotRegistered => continue,
ChannelStatus::Active { origin, mode, .. } => ChannelNode {
name,
mode: mode_word(mode),
state: "live",
origin: origin_word(origin),
reason: None,
},
ChannelStatus::Quiesced {
reason,
origin,
mode,
} => ChannelNode {
name,
mode: mode_word(mode),
state: "held",
origin: origin_word(origin),
reason: Some(reason),
},
};
channels.push(node);
}
Ok(TopologySnapshot {
channels,
services: services.responder_subjects()?,
})
}
const fn mode_word(mode: ChannelMode) -> &'static str {
match mode {
ChannelMode::Durable => "durable",
ChannelMode::Ephemeral => "ephemeral",
}
}
const fn origin_word(origin: ChannelOrigin) -> &'static str {
match origin {
ChannelOrigin::BootConfigured => "config",
ChannelOrigin::RuntimeRegistered => "runtime",
}
}