1use std::{path::PathBuf, sync::Arc};
7
8use anyhow::{Context, Result};
9use serde::{Deserialize, Serialize};
10use tokio::sync::RwLock;
11use tracing::{error, info, instrument, warn};
12
13use crate::{
14 Host::{Activation, HostConfig},
15 Host::ExtensionManager::ExtensionManagerImpl,
16 Transport::Strategy::Transport,
17 WASM::Runtime::{WASMConfig, WASMRuntime},
18};
19
20pub struct ExtensionHostImpl {
22 #[allow(dead_code)]
24 config:HostConfig,
25 transport:Transport,
27 extension_manager:Arc<ExtensionManagerImpl>,
29 activation_engine:Arc<Activation::ActivationEngine>,
31 wasm_runtime:Arc<WASMRuntime>,
33 active_extensions:Arc<RwLock<Vec<String>>>,
35 state:Arc<RwLock<HostState>>,
37}
38
39#[derive(Debug, Clone, PartialEq)]
41pub enum HostState {
42 Created,
44 Ready,
46 Running,
48 ShuttingDown,
50 Terminated,
52}
53
54#[derive(Debug, Clone, Default, Serialize, Deserialize)]
56pub struct HostStats {
57 pub loaded_extensions:usize,
59 pub active_extensions:usize,
61 pub total_activations:u64,
63 pub total_activation_time_ms:u64,
65 pub api_calls:u64,
67 pub errors:u64,
69 pub uptime_seconds:u64,
71}
72
73impl ExtensionHostImpl {
74 #[instrument(skip(transport))]
92 pub async fn new(transport:Transport) -> Result<Self> { Self::with_config(transport, HostConfig::default()).await }
93
94 #[instrument(skip(transport, config))]
96 pub async fn with_config(transport:Transport, config:HostConfig) -> Result<Self> {
97 info!("Creating extension host with config: {:?}", config);
98
99 transport.connect().await.context("Failed to connect transport")?;
101
102 let wasm_config = WASMConfig::new(512, 30000, true);
104 let wasm_runtime = Arc::new(WASMRuntime::new(wasm_config).await?);
105
106 let extension_manager = Arc::new(ExtensionManagerImpl::new(Arc::clone(&wasm_runtime), config.clone()));
108
109 let activation_engine = Arc::new(Activation::ActivationEngine::new(
111 Arc::clone(&extension_manager),
112 config.clone(),
113 ));
114
115 info!("Extension host created successfully");
116
117 Ok(Self {
118 config,
119 transport,
120 extension_manager,
121 activation_engine,
122 wasm_runtime,
123 active_extensions:Arc::new(RwLock::new(Vec::new())),
124 state:Arc::new(RwLock::new(HostState::Created)),
125 })
126 }
127
128 #[instrument(skip(self, path))]
130 pub async fn load_extension(&self, path:&PathBuf) -> Result<String> {
131 info!("Loading extension from: {:?}", path);
132
133 let extension_id = self
134 .extension_manager
135 .load_extension(path)
136 .await
137 .context("Failed to load extension")?;
138
139 info!("Extension loaded: {}", extension_id);
140
141 *self.state.write().await = HostState::Ready;
142
143 Ok(extension_id)
144 }
145
146 #[instrument(skip(self, extension_id))]
148 pub async fn unload_extension(&self, extension_id:&str) -> Result<()> {
149 info!("Unloading extension: {}", extension_id);
150
151 self.extension_manager
152 .unload_extension(extension_id)
153 .await
154 .context("Failed to unload extension")?;
155
156 info!("Extension unloaded: {}", extension_id);
157
158 Ok(())
159 }
160
161 #[instrument(skip(self, extension_id))]
163 pub async fn activate(&self, extension_id:&str) -> Result<()> {
164 info!("Activating extension: {}", extension_id);
165
166 let start = std::time::Instant::now();
167
168 let result = self
169 .activation_engine
170 .activate(extension_id)
171 .await
172 .context("Failed to activate extension")?;
173
174 let elapsed = start.elapsed().as_millis() as u64;
175
176 if result.success {
177 info!("Extension activated in {}ms: {}", elapsed, extension_id);
178
179 let mut active = self.active_extensions.write().await;
181 if !active.contains(&extension_id.to_string()) {
182 active.push(extension_id.to_string());
183 }
184
185 *self.state.write().await = HostState::Running;
186 } else {
187 error!("Extension activation failed: {}", extension_id);
188 }
189
190 Ok(())
191 }
192
193 #[instrument(skip(self, extension_id))]
195 pub async fn deactivate(&self, extension_id:&str) -> Result<()> {
196 info!("Deactivating extension: {}", extension_id);
197
198 self.activation_engine
199 .deactivate(extension_id)
200 .await
201 .context("Failed to deactivate extension")?;
202
203 let mut active = self.active_extensions.write().await;
205 active.retain(|id| id != extension_id);
206
207 info!("Extension deactivated: {}", extension_id);
208
209 Ok(())
210 }
211
212 #[instrument(skip(self))]
214 pub async fn activate_all(&self) -> Result<Vec<String>> {
215 info!("Activating all extensions");
216
217 let extensions = self.extension_manager.list_extensions().await;
218 let mut activated = Vec::new();
219 let mut failed = Vec::new();
220
221 for extension_id in extensions {
222 match self.activate(&extension_id).await {
223 Ok(_) => activated.push(extension_id),
224 Err(e) => {
225 error!("Failed to activate {}: {}", extension_id, e);
226 failed.push(extension_id);
227 },
228 }
229 }
230
231 warn!("Activated {} extensions, {} failed", activated.len(), failed.len());
232
233 Ok(activated)
234 }
235
236 #[instrument(skip(self))]
238 pub async fn deactivate_all(&self) -> Result<()> {
239 info!("Deactivating all extensions");
240
241 let active = self.active_extensions.read().await.clone();
242
243 for extension_id in active {
244 if let Err(e) = self.deactivate(&extension_id).await {
245 error!("Failed to deactivate {}: {}", extension_id, e);
246 }
247 }
248
249 *self.state.write().await = HostState::Ready;
250
251 Ok(())
252 }
253
254 pub async fn stats(&self) -> HostStats {
256 let active_extensions = self.active_extensions.read().await.len();
257 let loaded_extensions = self.extension_manager.list_extensions().await.len();
258 let extension_stats = self.extension_manager.stats().await;
259
260 HostStats {
261 loaded_extensions,
262 active_extensions,
263 total_activations:extension_stats.total_activated as u64,
264 total_activation_time_ms:extension_stats.total_activation_time_ms,
265 api_calls:0, errors:extension_stats.errors,
267 uptime_seconds:0, }
269 }
270
271 pub async fn state(&self) -> HostState { self.state.read().await.clone() }
273
274 pub fn transport(&self) -> &Transport { &self.transport }
276
277 pub fn extension_manager(&self) -> &Arc<ExtensionManagerImpl> { &self.extension_manager }
279
280 pub fn activation_engine(&self) -> &Arc<Activation::ActivationEngine> { &self.activation_engine }
282
283 pub fn wasm_runtime(&self) -> &Arc<WASMRuntime> { &self.wasm_runtime }
285
286 #[instrument(skip(self))]
288 pub async fn shutdown(&self) -> Result<()> {
289 info!("Shutting down extension host");
290
291 *self.state.write().await = HostState::ShuttingDown;
292
293 if let Err(e) = self.deactivate_all().await {
295 error!("Error deactivating extensions during shutdown: {}", e);
296 }
297
298 if let Err(e) = self.transport.close().await {
300 error!("Error closing transport during shutdown: {}", e);
301 }
302
303 if let Err(e) = self.wasm_runtime.shutdown().await {
305 error!("Error shutting down WASM runtime: {}", e);
306 }
307
308 *self.state.write().await = HostState::Terminated;
309
310 info!("Extension host shutdown complete");
311
312 Ok(())
313 }
314}
315
316impl Drop for ExtensionHostImpl {
317 fn drop(&mut self) {
318 info!("ExtensionHost dropped");
319 }
320}
321
322#[cfg(test)]
323mod tests {
324 use super::*;
325
326 #[tokio::test]
327 async fn test_host_state() {
328 assert_eq!(HostState::Created, HostState::Created);
329 assert_eq!(HostState::Ready, HostState::Ready);
330 assert_eq!(HostState::Running, HostState::Running);
331 }
332
333 #[test]
334 fn test_host_stats_default() {
335 let stats = HostStats::default();
336 assert_eq!(stats.loaded_extensions, 0);
337 assert_eq!(stats.active_extensions, 0);
338 }
339
340 #[test]
341 fn test_host_config_default() {
342 let config = HostConfig::default();
343 assert_eq!(config.max_extensions, 100);
344 assert_eq!(config.lazy_activation, true);
345 }
346}