Skip to main content

oxide_k/
kernel.rs

1//! The [`Kernel`] façade ties the three subsystems together.
2
3use crate::bus::MessageBus;
4use crate::error::Result;
5use crate::module::ModuleManager;
6use crate::registry::StateRegistry;
7
8/// The Oxide micro-kernel.
9///
10/// Owns the [`MessageBus`], [`ModuleManager`] and [`StateRegistry`] and exposes
11/// them as cheap-to-clone handles. Cloning the kernel itself is also cheap and
12/// produces a handle pointing at the same underlying state.
13#[derive(Clone, Debug)]
14pub struct Kernel {
15    bus: MessageBus,
16    modules: ModuleManager,
17    registry: StateRegistry,
18}
19
20impl Kernel {
21    /// Build a kernel backed by an in-memory state registry. Intended for
22    /// development, testing, and the bootstrap CLI.
23    pub async fn in_memory() -> Result<Self> {
24        let bus = MessageBus::new();
25        let registry = StateRegistry::in_memory().await?;
26        let modules = ModuleManager::new(bus.clone());
27        Ok(Self {
28            bus,
29            modules,
30            registry,
31        })
32    }
33
34    /// Build a kernel backed by an on-disk state registry at `path`.
35    pub async fn with_registry(path: &str) -> Result<Self> {
36        let bus = MessageBus::new();
37        let registry = StateRegistry::connect(path).await?;
38        let modules = ModuleManager::new(bus.clone());
39        Ok(Self {
40            bus,
41            modules,
42            registry,
43        })
44    }
45
46    /// Handle to the message bus.
47    pub fn bus(&self) -> &MessageBus {
48        &self.bus
49    }
50
51    /// Handle to the module manager.
52    pub fn modules(&self) -> &ModuleManager {
53        &self.modules
54    }
55
56    /// Handle to the global state registry.
57    pub fn registry(&self) -> &StateRegistry {
58        &self.registry
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[tokio::test]
67    async fn kernel_wires_subsystems() {
68        let kernel = Kernel::in_memory().await.unwrap();
69        // Every subsystem is reachable and the registry has been migrated.
70        assert_eq!(kernel.bus().subscriber_count().await, 0);
71        assert!(kernel.registry().list_modules().await.unwrap().is_empty());
72        assert!(kernel.modules().list().await.is_empty());
73    }
74}