liminal_server/console/
topology.rs1use liminal::channel::ChannelMode;
4
5use crate::ServerError;
6use crate::server::connection::channel_registry::{ChannelOrigin, ChannelStatus};
7use crate::server::connection::services::LiminalConnectionServices;
8
9#[derive(Clone, Debug, PartialEq, Eq)]
11pub struct ChannelNode {
12 pub name: String,
14 pub mode: &'static str,
16 pub state: &'static str,
18 pub origin: &'static str,
20 pub reason: Option<String>,
22}
23
24#[derive(Clone, Debug, Default, PartialEq, Eq)]
26pub struct TopologySnapshot {
27 pub channels: Vec<ChannelNode>,
29 pub services: Vec<String>,
31}
32
33pub fn snapshot(services: &LiminalConnectionServices) -> Result<TopologySnapshot, ServerError> {
40 let roster_error = |error: &dyn std::fmt::Display| ServerError::ListenerAccept {
41 message: format!("console topology: {error}"),
42 };
43 let census = services
44 .channel_census()
45 .map_err(|error| roster_error(&error))?;
46 let mut channels = Vec::with_capacity(census.len());
47 for (name, status) in census {
48 let node = match status {
49 ChannelStatus::NotRegistered => continue,
50 ChannelStatus::Active { origin, mode, .. } => ChannelNode {
51 name,
52 mode: mode_word(mode),
53 state: "live",
54 origin: origin_word(origin),
55 reason: None,
56 },
57 ChannelStatus::Quiesced {
58 reason,
59 origin,
60 mode,
61 } => ChannelNode {
62 name,
63 mode: mode_word(mode),
64 state: "held",
65 origin: origin_word(origin),
66 reason: Some(reason),
67 },
68 };
69 channels.push(node);
70 }
71 Ok(TopologySnapshot {
72 channels,
73 services: services.responder_subjects()?,
74 })
75}
76
77const fn mode_word(mode: ChannelMode) -> &'static str {
78 match mode {
79 ChannelMode::Durable => "durable",
80 ChannelMode::Ephemeral => "ephemeral",
81 }
82}
83
84const fn origin_word(origin: ChannelOrigin) -> &'static str {
85 match origin {
86 ChannelOrigin::BootConfigured => "config",
87 ChannelOrigin::RuntimeRegistered => "runtime",
88 }
89}