1use std::{path::PathBuf, sync::Arc};
7
8use anyhow::{Context, Result};
9use serde::{Deserialize, Serialize};
10use tokio::sync::RwLock;
11
12use crate::{
13 Host::{Activation, ExtensionManager::ExtensionManagerImpl, HostConfig},
14 Transport::Strategy::Transport,
15 WASM::Runtime::{WASMConfig, WASMRuntime},
16 dev_log,
17};
18
19pub struct ExtensionHostImpl {
21 #[allow(dead_code)]
23 config:HostConfig,
24
25 transport:Transport,
27
28 extension_manager:Arc<ExtensionManagerImpl>,
30
31 activation_engine:Arc<Activation::ActivationEngine>,
33
34 wasm_runtime:Arc<WASMRuntime>,
36
37 active_extensions:Arc<RwLock<Vec<String>>>,
39
40 state:Arc<RwLock<HostState>>,
42}
43
44#[derive(Debug, Clone, PartialEq)]
46pub enum HostState {
47 Created,
49
50 Ready,
52
53 Running,
55
56 ShuttingDown,
58
59 Terminated,
61}
62
63#[derive(Debug, Clone, Default, Serialize, Deserialize)]
65pub struct HostStats {
66 pub loaded_extensions:usize,
68
69 pub active_extensions:usize,
71
72 pub total_activations:u64,
74
75 pub total_activation_time_ms:u64,
77
78 pub api_calls:u64,
80
81 pub errors:u64,
83
84 pub uptime_seconds:u64,
86}
87
88impl ExtensionHostImpl {
89 pub async fn new(transport:Transport) -> Result<Self> { Self::with_config(transport, HostConfig::default()).await }
107
108 pub async fn with_config(transport:Transport, config:HostConfig) -> Result<Self> {
110 dev_log!("grove", "Creating extension host with config: {:?}", config);
111
112 transport.connect().await.context("Failed to connect transport")?;
114
115 let wasm_config = WASMConfig::new(512, 30000, true);
117
118 let wasm_runtime = Arc::new(WASMRuntime::new(wasm_config).await?);
119
120 let extension_manager = Arc::new(ExtensionManagerImpl::new(Arc::clone(&wasm_runtime), config.clone()));
122
123 let activation_engine = Arc::new(Activation::ActivationEngine::new(
125 Arc::clone(&extension_manager),
126 config.clone(),
127 ));
128
129 dev_log!("grove", "Extension host created successfully");
130
131 Ok(Self {
132 config,
133 transport,
134 extension_manager,
135 activation_engine,
136 wasm_runtime,
137 active_extensions:Arc::new(RwLock::new(Vec::new())),
138 state:Arc::new(RwLock::new(HostState::Created)),
139 })
140 }
141
142 pub async fn load_extension(&self, path:&PathBuf) -> Result<String> {
144 dev_log!("extensions", "Loading extension from: {:?}", path);
145
146 let extension_id = self
147 .extension_manager
148 .load_extension(path)
149 .await
150 .context("Failed to load extension")?;
151
152 dev_log!("extensions", "Extension loaded: {}", extension_id);
153
154 *self.state.write().await = HostState::Ready;
155
156 Ok(extension_id)
157 }
158
159 pub async fn unload_extension(&self, extension_id:&str) -> Result<()> {
161 dev_log!("extensions", "Unloading extension: {}", extension_id);
162
163 self.extension_manager
164 .unload_extension(extension_id)
165 .await
166 .context("Failed to unload extension")?;
167
168 dev_log!("extensions", "Extension unloaded: {}", extension_id);
169
170 Ok(())
171 }
172
173 pub async fn activate(&self, extension_id:&str) -> Result<()> {
175 dev_log!("extensions", "Activating extension: {}", extension_id);
176
177 let start = std::time::Instant::now();
178
179 let result = self
180 .activation_engine
181 .activate(extension_id)
182 .await
183 .context("Failed to activate extension")?;
184
185 let elapsed = start.elapsed().as_millis() as u64;
186
187 if result.success {
188 dev_log!("extensions", "Extension activated in {}ms: {}", elapsed, extension_id);
189
190 let mut active = self.active_extensions.write().await;
192
193 if !active.contains(&extension_id.to_string()) {
194 active.push(extension_id.to_string());
195 }
196
197 *self.state.write().await = HostState::Running;
198 } else {
199 dev_log!("extensions", "error: extension activation failed: {}", extension_id);
200 }
201
202 Ok(())
203 }
204
205 pub async fn deactivate(&self, extension_id:&str) -> Result<()> {
207 dev_log!("extensions", "Deactivating extension: {}", extension_id);
208
209 self.activation_engine
210 .deactivate(extension_id)
211 .await
212 .context("Failed to deactivate extension")?;
213
214 let mut active = self.active_extensions.write().await;
216
217 active.retain(|id| id != extension_id);
218
219 dev_log!("extensions", "Extension deactivated: {}", extension_id);
220
221 Ok(())
222 }
223
224 pub async fn activate_all(&self) -> Result<Vec<String>> {
226 dev_log!("extensions", "Activating all extensions");
227
228 let extensions = self.extension_manager.list_extensions().await;
229
230 let mut activated = Vec::new();
231
232 let mut failed = Vec::new();
233
234 for extension_id in extensions {
235 match self.activate(&extension_id).await {
236 Ok(_) => activated.push(extension_id),
237
238 Err(e) => {
239 dev_log!("extensions", "error: failed to activate {}: {}", extension_id, e);
240
241 failed.push(extension_id);
242 },
243 }
244 }
245
246 dev_log!(
247 "extensions",
248 "warn: activated {} extensions, {} failed",
249 activated.len(),
250 failed.len()
251 );
252
253 Ok(activated)
254 }
255
256 pub async fn deactivate_all(&self) -> Result<()> {
258 dev_log!("extensions", "Deactivating all extensions");
259
260 let active = self.active_extensions.read().await.clone();
261
262 for extension_id in active {
263 if let Err(e) = self.deactivate(&extension_id).await {
264 dev_log!("extensions", "error: failed to deactivate {}: {}", extension_id, e);
265 }
266 }
267
268 *self.state.write().await = HostState::Ready;
269
270 Ok(())
271 }
272
273 pub async fn stats(&self) -> HostStats {
275 let active_extensions = self.active_extensions.read().await.len();
276
277 let loaded_extensions = self.extension_manager.list_extensions().await.len();
278
279 let extension_stats = self.extension_manager.stats().await;
280
281 HostStats {
282 loaded_extensions,
283
284 active_extensions,
285
286 total_activations:extension_stats.total_activated as u64,
287
288 total_activation_time_ms:extension_stats.total_activation_time_ms,
289
290 api_calls:0, errors:extension_stats.errors,
292
293 uptime_seconds:0, }
295 }
296
297 pub async fn state(&self) -> HostState { self.state.read().await.clone() }
299
300 pub fn transport(&self) -> &Transport { &self.transport }
302
303 pub fn extension_manager(&self) -> &Arc<ExtensionManagerImpl> { &self.extension_manager }
305
306 pub fn activation_engine(&self) -> &Arc<Activation::ActivationEngine> { &self.activation_engine }
308
309 pub fn wasm_runtime(&self) -> &Arc<WASMRuntime> { &self.wasm_runtime }
311
312 pub async fn shutdown(&self) -> Result<()> {
314 dev_log!("lifecycle", "Shutting down extension host");
315
316 *self.state.write().await = HostState::ShuttingDown;
317
318 if let Err(e) = self.deactivate_all().await {
320 dev_log!("lifecycle", "error: error deactivating extensions during shutdown: {}", e);
321 }
322
323 if let Err(e) = self.transport.close().await {
325 dev_log!("lifecycle", "error: error closing transport during shutdown: {}", e);
326 }
327
328 if let Err(e) = self.wasm_runtime.shutdown().await {
330 dev_log!("wasm", "error: error shutting down WASM runtime: {}", e);
331 }
332
333 *self.state.write().await = HostState::Terminated;
334
335 dev_log!("lifecycle", "Extension host shutdown complete");
336
337 Ok(())
338 }
339}
340
341impl Drop for ExtensionHostImpl {
342 fn drop(&mut self) {
343 dev_log!("lifecycle", "ExtensionHost dropped");
344 }
345}
346
347#[cfg(test)]
348mod tests {
349
350 use super::*;
351
352 #[tokio::test]
353 async fn test_host_state() {
354 assert_eq!(HostState::Created, HostState::Created);
355
356 assert_eq!(HostState::Ready, HostState::Ready);
357
358 assert_eq!(HostState::Running, HostState::Running);
359 }
360
361 #[test]
362 fn test_host_stats_default() {
363 let stats = HostStats::default();
364
365 assert_eq!(stats.loaded_extensions, 0);
366
367 assert_eq!(stats.active_extensions, 0);
368 }
369
370 #[test]
371 fn test_host_config_default() {
372 let config = HostConfig::default();
373
374 assert_eq!(config.max_extensions, 100);
375
376 assert_eq!(config.lazy_activation, true);
377 }
378}