use std::sync::Arc;
use std::thread;
use std::time::Duration;
use sochdb_kernel::plugin_hot_reload::{
EpochTracker, HotReloadManager, HotReloadState, HotReloadablePlugin,
};
use sochdb_kernel::plugin_manifest::ManifestBuilder;
use sochdb_kernel::wasm_runtime::{WasmInstanceConfig, WasmPluginInstance};
fn main() {
println!("═══════════════════════════════════════════════════════════════");
println!(" SochDB Hot-Reload Plugin System - Demo");
println!("═══════════════════════════════════════════════════════════════\n");
println!("Step 1: Epoch-Based Draining Mechanism\n");
let tracker = EpochTracker::new();
println!(" Initial epoch: {}", tracker.current());
let guard = tracker.enter();
println!(" After entering - epoch refs: {}", tracker.refs_for_epoch(0));
let new_epoch = tracker.advance();
println!(" After advancing - current epoch: {}", new_epoch);
println!(" Old epoch (0) still has refs: {}", tracker.refs_for_epoch(0));
drop(guard);
println!(" After dropping guard - epoch 0 refs: {}", tracker.refs_for_epoch(0));
let drained = tracker.wait_drain(0, Duration::from_millis(10));
println!(" Drain epoch 0 succeeded: {}", drained);
println!();
println!("Step 2: Creating Hot-Reloadable Plugin\n");
let config = WasmInstanceConfig::default();
let instance = WasmPluginInstance::new("my-plugin", b"wasm v1.0", config).unwrap();
instance.init().unwrap();
let manifest = ManifestBuilder::new("my-plugin", "1.0.0")
.author("SochDB Team")
.description("Demo plugin")
.export("on_insert")
.export("on_update")
.build()
.unwrap();
let plugin = HotReloadablePlugin::new("my-plugin", Arc::new(instance), manifest);
println!(" Plugin name: {}", plugin.name());
println!(" Plugin state: {:?}", plugin.state());
println!(" Initial version: {}", plugin.stats().version);
println!();
println!("Step 3: Calling Plugin (Epoch-Protected)\n");
let result = plugin.call("on_insert", &[]).unwrap();
println!(" on_insert() result: {:?}", result);
let result = plugin.call("on_update", &[]).unwrap();
println!(" on_update() result: {:?}", result);
let stats = plugin.stats();
println!(" Stats - version: {}, successful upgrades: {}", stats.version, stats.successful_upgrades);
println!();
println!("Step 4: Hot-Reload Upgrade (v1.0 → v2.0)\n");
let new_manifest = ManifestBuilder::new("my-plugin", "2.0.0")
.author("SochDB Team")
.description("Demo plugin v2 with improvements")
.export("on_insert")
.export("on_update")
.export("on_delete") .build()
.unwrap();
println!(" State before upgrade: {:?}", plugin.state());
plugin.prepare_upgrade(b"wasm v2.0 bytes", new_manifest).unwrap();
println!(" State after prepare: {:?}", plugin.state());
plugin.execute_upgrade().unwrap();
println!(" State after execute: {:?}", plugin.state());
let stats = plugin.stats();
println!(" Stats after upgrade:");
println!(" - Version: {}", stats.version);
println!(" - Successful upgrades: {}", stats.successful_upgrades);
println!(" - Total drain time: {}μs", stats.total_drain_time_us);
println!();
println!("Step 5: Hot-Reload Manager (Multiple Plugins)\n");
let manager = HotReloadManager::new();
for i in 1..=3 {
let name = format!("service-{}", i);
let config = WasmInstanceConfig::default();
let instance = WasmPluginInstance::new(&name, b"wasm bytes", config).unwrap();
instance.init().unwrap();
let manifest = ManifestBuilder::new(&name, "1.0.0")
.export("on_insert")
.build()
.unwrap();
manager.register(&name, Arc::new(instance), manifest).unwrap();
}
println!(" Registered plugins: {:?}", manager.list());
let new_manifest = ManifestBuilder::new("service-2", "2.0.0")
.export("on_insert")
.build()
.unwrap();
manager.upgrade("service-2", b"new wasm", new_manifest).unwrap();
println!(" Upgraded service-2 to v2.0.0");
for (name, stats) in manager.all_stats() {
println!(" {} - version: {}, upgrades: {}", name, stats.version, stats.successful_upgrades);
}
println!();
println!("Step 6: Concurrent Access During Upgrade\n");
let config = WasmInstanceConfig::default();
let instance = WasmPluginInstance::new("concurrent-plugin", b"v1", config).unwrap();
instance.init().unwrap();
let manifest = ManifestBuilder::new("concurrent-plugin", "1.0.0")
.export("on_insert")
.build()
.unwrap();
let plugin = Arc::new(HotReloadablePlugin::new(
"concurrent-plugin",
Arc::new(instance),
manifest,
));
let handles: Vec<_> = (0..4)
.map(|i| {
let p = plugin.clone();
thread::spawn(move || {
for j in 0..5 {
let _ = p.call("on_insert", &[]);
thread::sleep(Duration::from_millis(1));
}
println!(" Thread {} completed 5 calls", i);
})
})
.collect();
thread::sleep(Duration::from_millis(5));
println!(" Initiating upgrade while threads are running...");
let new_manifest = ManifestBuilder::new("concurrent-plugin", "2.0.0")
.export("on_insert")
.build()
.unwrap();
match plugin.upgrade(b"v2 bytes", new_manifest) {
Ok(()) => println!(" ✅ Upgrade succeeded during concurrent access!"),
Err(e) => println!(" ⚠️ Upgrade failed (expected if threads held refs): {}", e),
}
for h in handles {
h.join().unwrap();
}
println!();
println!("═══════════════════════════════════════════════════════════════");
println!(" ✅ Hot-Reload Demo completed!");
println!("═══════════════════════════════════════════════════════════════");
}