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::Transport,
17 WASM::Runtime::{WASMConfig, WASMRuntime},
18};
19
20pub struct ExtensionHostImpl {
22 config:HostConfig,
24 transport:Transport,
26 extension_manager:Arc<ExtensionManagerImpl>,
28 activation_engine:Arc<Activation::ActivationEngine>,
30 wasm_runtime:Arc<WASMRuntime>,
32 active_extensions:Arc<RwLock<Vec<String>>>,
34 state:Arc<RwLock<HostState>>,
36}
37
38#[derive(Debug, Clone, PartialEq)]
40pub enum HostState {
41 Created,
43 Ready,
45 Running,
47 ShuttingDown,
49 Terminated,
51}
52
53#[derive(Debug, Clone, Default, Serialize, Deserialize)]
55pub struct HostStats {
56 pub loaded_extensions:usize,
58 pub active_extensions:usize,
60 pub total_activations:u64,
62 pub total_activation_time_ms:u64,
64 pub api_calls:u64,
66 pub errors:u64,
68 pub uptime_seconds:u64,
70}
71
72impl ExtensionHostImpl {
73 #[instrument(skip(transport))]
91 pub async fn new(transport:Transport) -> Result<Self> { Self::with_config(transport, HostConfig::default()).await }
92
93 #[instrument(skip(transport, config))]
95 pub async fn with_config(transport:Transport, config:HostConfig) -> Result<Self> {
96 info!("Creating extension host with config: {:?}", config);
97
98 transport.connect().await.context("Failed to connect transport")?;
100
101 let wasm_config = WASMConfig::new(512, 30000, true);
103 let wasm_runtime = Arc::new(WASMRuntime::new(wasm_config).await?);
104
105 let extension_manager = Arc::new(ExtensionManagerImpl::new(Arc::clone(&wasm_runtime), config.clone()));
107
108 let activation_engine = Arc::new(Activation::ActivationEngine::new(
110 Arc::clone(&extension_manager),
111 config.clone(),
112 ));
113
114 info!("Extension host created successfully");
115
116 Ok(Self {
117 config,
118 transport,
119 extension_manager,
120 activation_engine,
121 wasm_runtime,
122 active_extensions:Arc::new(RwLock::new(Vec::new())),
123 state:Arc::new(RwLock::new(HostState::Created)),
124 })
125 }
126
127 #[instrument(skip(self, path))]
129 pub async fn load_extension(&self, path:&PathBuf) -> Result<String> {
130 info!("Loading extension from: {:?}", path);
131
132 let extension_id = self
133 .extension_manager
134 .load_extension(path)
135 .await
136 .context("Failed to load extension")?;
137
138 info!("Extension loaded: {}", extension_id);
139
140 *self.state.write().await = HostState::Ready;
141
142 Ok(extension_id)
143 }
144
145 #[instrument(skip(self, extension_id))]
147 pub async fn unload_extension(&self, extension_id:&str) -> Result<()> {
148 info!("Unloading extension: {}", extension_id);
149
150 self.extension_manager
151 .unload_extension(extension_id)
152 .await
153 .context("Failed to unload extension")?;
154
155 info!("Extension unloaded: {}", extension_id);
156
157 Ok(())
158 }
159
160 #[instrument(skip(self, extension_id))]
162 pub async fn activate(&self, extension_id:&str) -> Result<()> {
163 info!("Activating extension: {}", extension_id);
164
165 let start = std::time::Instant::now();
166
167 let result = self
168 .activation_engine
169 .activate(extension_id)
170 .await
171 .context("Failed to activate extension")?;
172
173 let elapsed = start.elapsed().as_millis() as u64;
174
175 if result.success {
176 info!("Extension activated in {}ms: {}", elapsed, extension_id);
177
178 let mut active = self.active_extensions.write().await;
180 if !active.contains(&extension_id.to_string()) {
181 active.push(extension_id.to_string());
182 }
183
184 *self.state.write().await = HostState::Running;
185 } else {
186 error!("Extension activation failed: {}", extension_id);
187 }
188
189 Ok(())
190 }
191
192 #[instrument(skip(self, extension_id))]
194 pub async fn deactivate(&self, extension_id:&str) -> Result<()> {
195 info!("Deactivating extension: {}", extension_id);
196
197 self.activation_engine
198 .deactivate(extension_id)
199 .await
200 .context("Failed to deactivate extension")?;
201
202 let mut active = self.active_extensions.write().await;
204 active.retain(|id| id != extension_id);
205
206 info!("Extension deactivated: {}", extension_id);
207
208 Ok(())
209 }
210
211 #[instrument(skip(self))]
213 pub async fn activate_all(&self) -> Result<Vec<String>> {
214 info!("Activating all extensions");
215
216 let extensions = self.extension_manager.list_extensions().await;
217 let mut activated = Vec::new();
218 let mut failed = Vec::new();
219
220 for extension_id in extensions {
221 match self.activate(&extension_id).await {
222 Ok(_) => activated.push(extension_id),
223 Err(e) => {
224 error!("Failed to activate {}: {}", extension_id, e);
225 failed.push(extension_id);
226 },
227 }
228 }
229
230 warn!("Activated {} extensions, {} failed", activated.len(), failed.len());
231
232 Ok(activated)
233 }
234
235 #[instrument(skip(self))]
237 pub async fn deactivate_all(&self) -> Result<()> {
238 info!("Deactivating all extensions");
239
240 let active = self.active_extensions.read().await.clone();
241
242 for extension_id in active {
243 if let Err(e) = self.deactivate(&extension_id).await {
244 error!("Failed to deactivate {}: {}", extension_id, e);
245 }
246 }
247
248 *self.state.write().await = HostState::Ready;
249
250 Ok(())
251 }
252
253 pub async fn stats(&self) -> HostStats {
255 let active_extensions = self.active_extensions.read().await.len();
256 let loaded_extensions = self.extension_manager.list_extensions().await.len();
257 let extension_stats = self.extension_manager.stats().await;
258
259 HostStats {
260 loaded_extensions,
261 active_extensions,
262 total_activations:extension_stats.total_activated as u64,
263 total_activation_time_ms:extension_stats.total_activation_time_ms,
264 api_calls:0, errors:extension_stats.errors,
266 uptime_seconds:0, }
268 }
269
270 pub async fn state(&self) -> HostState { self.state.read().await.clone() }
272
273 pub fn transport(&self) -> &Transport { &self.transport }
275
276 pub fn extension_manager(&self) -> &Arc<ExtensionManagerImpl> { &self.extension_manager }
278
279 pub fn activation_engine(&self) -> &Arc<Activation::ActivationEngine> { &self.activation_engine }
281
282 pub fn wasm_runtime(&self) -> &Arc<WASMRuntime> { &self.wasm_runtime }
284
285 #[instrument(skip(self))]
287 pub async fn shutdown(&self) -> Result<()> {
288 info!("Shutting down extension host");
289
290 *self.state.write().await = HostState::ShuttingDown;
291
292 if let Err(e) = self.deactivate_all().await {
294 error!("Error deactivating extensions during shutdown: {}", e);
295 }
296
297 if let Err(e) = self.transport.close().await {
299 error!("Error closing transport during shutdown: {}", e);
300 }
301
302 if let Err(e) = self.wasm_runtime.shutdown().await {
304 error!("Error shutting down WASM runtime: {}", e);
305 }
306
307 *self.state.write().await = HostState::Terminated;
308
309 info!("Extension host shutdown complete");
310
311 Ok(())
312 }
313}
314
315impl Drop for ExtensionHostImpl {
316 fn drop(&mut self) {
317 info!("ExtensionHost dropped");
318 }
319}
320
321#[cfg(test)]
322mod tests {
323 use super::*;
324
325 #[tokio::test]
326 async fn test_host_state() {
327 assert_eq!(HostState::Created, HostState::Created);
328 assert_eq!(HostState::Ready, HostState::Ready);
329 assert_eq!(HostState::Running, HostState::Running);
330 }
331
332 #[test]
333 fn test_host_stats_default() {
334 let stats = HostStats::default();
335 assert_eq!(stats.loaded_extensions, 0);
336 assert_eq!(stats.active_extensions, 0);
337 }
338
339 #[test]
340 fn test_host_config_default() {
341 let config = HostConfig::default();
342 assert_eq!(config.max_extensions, 100);
343 assert_eq!(config.lazy_activation, true);
344 }
345}