kinetic/transforms/wasm/
runtime.rs1use std::sync::Arc;
4use tokio::sync::RwLock;
5
6#[derive(Debug)]
8pub struct WasmRuntime {
9 engine: Arc<wasmtime::Engine>,
11 module: Arc<RwLock<wasmtime::Module>>,
13 module_hash: Arc<RwLock<String>>,
15}
16
17impl WasmRuntime {
18 pub fn new(engine: Arc<wasmtime::Engine>, wasm_bytes: &[u8]) -> anyhow::Result<Self> {
20 let module = wasmtime::Module::new(&engine, wasm_bytes)?;
21 let hash = sha256(wasm_bytes);
22
23 Ok(Self {
24 engine,
25 module: Arc::new(RwLock::new(module)),
26 module_hash: Arc::new(RwLock::new(hash)),
27 })
28 }
29
30 pub async fn get_module_hash(&self) -> String {
32 self.module_hash.read().await.clone()
33 }
34
35 pub async fn hot_swap(&self, new_wasm_bytes: &[u8]) -> anyhow::Result<()> {
37 let new_module = wasmtime::Module::new(&self.engine, new_wasm_bytes)?;
39 let new_hash = sha256(new_wasm_bytes);
40
41 let mut module_guard = self.module.write().await;
43 let mut hash_guard = self.module_hash.write().await;
44
45 *module_guard = new_module;
46 *hash_guard = new_hash;
47
48 Ok(())
49 }
50
51 pub async fn instantiate(&self) -> anyhow::Result<wasmtime::Instance> {
53 let module = self.module.read().await;
54
55 let mut store = wasmtime::Store::new(&self.engine, ());
58
59 let instance = wasmtime::Instance::new(&mut store, &module, &[])?;
61
62 Ok(instance)
67 }
68
69 pub async fn check_abi_compatibility(&self) -> bool {
71 let module = self.module.read().await;
72
73 let required_exports = ["transform", "get_schema"];
75
76 for export in &required_exports {
77 if module.get_export(export).is_none() {
78 return false;
79 }
80 }
81
82 true
83 }
84}
85
86fn sha256(data: &[u8]) -> String {
87 use sha2::{Digest, Sha256};
88 let mut hasher = Sha256::new();
89 hasher.update(data);
90 hex::encode(hasher.finalize())
91}
92
93#[derive(Debug, Clone)]
95pub struct HotSwapConfig {
96 pub enabled: bool,
98 pub health_gate_secs: u64,
100 pub auto_rollback: bool,
102 pub dev_mode: bool,
104}
105
106impl Default for HotSwapConfig {
107 fn default() -> Self {
108 Self {
109 enabled: false,
110 health_gate_secs: 30,
111 auto_rollback: true,
112 dev_mode: false,
113 }
114 }
115}