use anyhow::{Context, Result};
use dashmap::DashMap;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use wasmtime::component::Component;
use wasmtime::{Config, Engine};
pub struct WasmCache {
engine: Engine,
components: DashMap<PathBuf, Arc<Component>>,
}
impl WasmCache {
pub fn new() -> Result<Self> {
let mut config = Config::new();
config.wasm_component_model(true);
let engine = Engine::new(&config)?;
Ok(Self {
engine,
components: DashMap::new(),
})
}
pub fn get_or_load(&self, path: &Path) -> Result<Arc<Component>> {
if let Some(component) = self.components.get(path) {
return Ok::<Arc<Component>, anyhow::Error>(component.clone());
}
let component = Component::from_file(&self.engine, path)
.map_err(anyhow::Error::from)
.with_context(|| format!("failed to load wasm decree: {}", path.display()))?;
let component = Arc::new(component);
self.components
.insert(path.to_path_buf(), component.clone());
tracing::info!("Cached WASM component: {}", path.display());
Ok(component)
}
pub fn clear(&self) {
self.components.clear();
tracing::info!("Cleared WASM component cache");
}
#[must_use]
pub fn stats(&self) -> WasmCacheStats {
WasmCacheStats {
entries: self.components.len(),
}
}
}
impl Default for WasmCache {
fn default() -> Self {
Self::new().expect("Failed to create WASM cache")
}
}
#[derive(Debug, Clone)]
pub struct WasmCacheStats {
pub entries: usize,
}
#[cfg(test)]
mod tests;