hyperion_framework/containerisation/
hyperion_container_factory.rs1use std::fmt::Debug;
25use std::fs;
26use std::path::PathBuf;
27use std::str::FromStr;
28use std::sync::{Arc as StdArc, atomic::AtomicUsize};
29
30use log::LevelFilter;
32use serde::{Serialize, de::DeserializeOwned};
33use tokio::sync::{Notify, mpsc};
34use tokio::task;
35use tokio::time::{Duration, sleep};
36
37use crate::containerisation::client_broker::ClientBroker;
39use crate::containerisation::hyperion_container::HyperionContainer;
40use crate::containerisation::traits::{
41 ContainerIdentidy, HeartbeatConfigProvider, HyperionContainerDirectiveMessage,
42 HyperionHeartbeatMessage, Initialisable, LogLevel, Run,
43};
44use crate::heartbeat::handler::{HeartbeatMissedHandler, HeartbeatTimeoutHandler};
45use crate::logging::logging_service::initialise_logger;
46use crate::network::network_topology::NetworkTopology;
47use crate::network::server::Server;
48use crate::utilities::load_config;
49
50pub async fn create<A, C, T>(
54 config_path_str: &str,
55 network_topology_path_str: &str,
56 container_state: StdArc<AtomicUsize>,
57 container_state_notify: StdArc<Notify>,
58 main_rx: mpsc::Receiver<T>,
59 timeout_handler: Option<Box<dyn HeartbeatTimeoutHandler>>,
60 missed_handler: Option<Box<dyn HeartbeatMissedHandler>>,
61) -> HyperionContainer<T>
62where
63 A: Initialisable<ConfigType = C> + Run<Message = T> + Send + 'static + Sync + Debug,
64 C: Debug
65 + Send
66 + 'static
67 + DeserializeOwned
68 + Sync
69 + LogLevel
70 + ContainerIdentidy
71 + HeartbeatConfigProvider,
72 T: HyperionContainerDirectiveMessage
73 + HyperionHeartbeatMessage
74 + Debug
75 + Send
76 + 'static
77 + DeserializeOwned
78 + Sync
79 + Clone
80 + Serialize,
81{
82 let config_path: PathBuf = fs::canonicalize(config_path_str)
84 .unwrap_or_else(|e| panic!("Could not canonicalize '{config_path_str}': {e}"));
85 let component_config: StdArc<C> = load_config::load_config::<C>(&config_path)
86 .unwrap_or_else(|e| panic!("Failed to load component config from '{config_path:?}': {e}"));
87 let network_topology_path: PathBuf = fs::canonicalize(network_topology_path_str)
88 .unwrap_or_else(|e| panic!("Could not canonicalize '{network_topology_path_str}': {e}"));
89 let network_topology: StdArc<NetworkTopology> =
90 load_config::load_config::<NetworkTopology>(&network_topology_path).unwrap_or_else(|e| {
91 panic!("Failed to load network topology from '{network_topology_path:?}': {e}")
92 });
93
94 let log_level: LevelFilter = LevelFilter::from_str(component_config.log_level())
96 .unwrap_or_else(|e| {
97 println!("Log level was not parsed correctly: {e:?}\nDefaulting to 'Trace' log level.");
99 LevelFilter::Trace
100 });
101 initialise_logger(log_level).unwrap_or_else(|e| panic!("Failed to initialise logger: {e:?}"));
102
103 for (key, value) in component_config.container_identity().iter() {
105 log::debug!("{key}: {value}");
106 }
107
108 log::info!(
110 "Building Hyperion Container for {}...",
111 component_config
112 .container_identity()
113 .get("name")
114 .unwrap_or(&"Unknown".to_string())
115 );
116
117 let component_archetype = A::initialise(
119 container_state.clone(),
120 container_state_notify.clone(),
121 component_config.clone(),
122 );
123
124 let (server_tx, server_rx) = mpsc::channel::<T>(32);
126 let arc_server: StdArc<Server<T>> = Server::new(
127 network_topology.server_address.clone(),
128 server_tx,
129 container_state.clone(),
130 container_state_notify.clone(),
131 );
132 task::spawn(async move {
133 if let Err(e) = Server::run(arc_server).await {
135 log::error!("Server encountered an error: {e:?}");
136 }
137 });
138
139 sleep(Duration::from_secs(2)).await;
141
142 let client_broker: ClientBroker<T> = ClientBroker::init(
144 network_topology,
145 container_state.clone(),
146 container_state_notify.clone(),
147 );
148
149 sleep(Duration::from_secs(2)).await;
151
152 let container_name = component_config
153 .container_identity()
154 .get("name")
155 .cloned()
156 .unwrap_or_else(|| "Unknown".to_string());
157
158 let heartbeat_config = component_config.heartbeat_config();
159
160 HyperionContainer::<T>::create(
162 component_archetype,
163 container_state,
164 container_state_notify,
165 client_broker,
166 main_rx,
167 server_rx,
168 heartbeat_config,
169 container_name,
170 timeout_handler,
171 missed_handler,
172 )
173}