use async_trait::async_trait;
use oxide_k::bus::{Command, Event, Message};
use oxide_k::module::{Module, ModuleKind, ModuleMetadata};
use oxide_k::{Kernel, Result};
use tracing::{info, Level};
struct EchoModule;
#[async_trait]
impl Module for EchoModule {
fn metadata(&self) -> ModuleMetadata {
ModuleMetadata {
id: "echo".into(),
name: "Echo".into(),
version: "0.1.0".into(),
kind: ModuleKind::Native,
description: Some("Demo module that echoes Ping commands.".into()),
}
}
async fn start(&mut self) -> Result<()> {
info!(module = "echo", "starting");
Ok(())
}
async fn stop(&mut self) -> Result<()> {
info!(module = "echo", "stopping");
Ok(())
}
}
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_max_level(Level::INFO)
.with_target(false)
.init();
info!("Booting Oxide Kernel...");
let kernel = Kernel::in_memory().await?;
let mut sub = kernel.bus().subscribe().await;
kernel.modules().register_native(EchoModule).await?;
kernel.modules().init("echo").await?;
let meta = ModuleMetadata {
id: "echo".into(),
name: "Echo".into(),
version: "0.1.0".into(),
kind: ModuleKind::Native,
description: Some("Demo module that echoes Ping commands.".into()),
};
kernel
.registry()
.upsert_module(&meta, oxide_k::module::ModuleState::Loaded)
.await?;
kernel
.registry()
.set_config("kernel.greeting", &"Hello, agent.")
.await?;
let greeting: String = kernel.registry().get_config("kernel.greeting").await?;
info!(greeting, "loaded greeting from registry");
kernel.modules().start("echo").await?;
kernel
.registry()
.set_module_state("echo", oxide_k::module::ModuleState::Running)
.await?;
let bus_clone = kernel.bus().clone();
let mut module_sub = bus_clone.subscribe().await;
let echo_task = tokio::spawn(async move {
while let Some(envelope) = module_sub.receiver.recv().await {
if let Message::Command(Command::Ping) = envelope.message {
let _ = bus_clone
.emit_event(
"echo",
Event::Pong {
from: "echo".into(),
},
)
.await;
break;
}
}
});
kernel.bus().send_command("kernel", Command::Ping).await?;
for _ in 0..3 {
if let Some(env) = sub.receiver.recv().await {
info!(?env.source, ?env.message, "bus event");
if matches!(env.message, Message::Event(Event::Pong { .. })) {
break;
}
}
}
kernel.modules().stop("echo").await?;
kernel
.registry()
.set_module_state("echo", oxide_k::module::ModuleState::Stopped)
.await?;
let _ = echo_task.await;
info!(
modules = ?kernel.registry().list_modules().await?,
"final registry state"
);
info!("Kernel demo complete.");
Ok(())
}