Skip to main content

batuta/serve/banco/
events.rs

1//! Real-time event bus for WebSocket notifications.
2//!
3//! Events are broadcast to all connected WebSocket clients.
4//! Producers (handlers) call `EventBus::emit()` — all subscribers receive the event.
5
6use serde::Serialize;
7use tokio::sync::broadcast;
8
9/// Event types emitted by Banco operations.
10#[derive(Debug, Clone, Serialize)]
11#[serde(tag = "type", content = "data")]
12#[serde(rename_all = "snake_case")]
13pub enum BancoEvent {
14    /// Model loaded into slot.
15    ModelLoaded { model_id: String, format: String },
16    /// Model unloaded from slot.
17    ModelUnloaded,
18    /// Training run started.
19    TrainingStarted { run_id: String, method: String },
20    /// Training metric emitted.
21    TrainingMetric { run_id: String, step: u64, loss: f32 },
22    /// Training run completed.
23    TrainingComplete { run_id: String },
24    /// File uploaded.
25    FileUploaded { file_id: String, name: String },
26    /// RAG index updated.
27    RagIndexed { doc_count: usize, chunk_count: usize },
28    /// Model merge completed.
29    MergeComplete { merge_id: String, strategy: String },
30    /// System status change.
31    SystemEvent { message: String },
32}
33
34/// Broadcast event bus — multiple producers, multiple consumers.
35pub struct EventBus {
36    sender: broadcast::Sender<String>,
37}
38
39impl EventBus {
40    /// Create a new event bus with the given channel capacity.
41    #[must_use]
42    pub fn new(capacity: usize) -> Self {
43        let (sender, _) = broadcast::channel(capacity);
44        Self { sender }
45    }
46
47    /// Emit an event to all subscribers.
48    pub fn emit(&self, event: &BancoEvent) {
49        if let Ok(json) = serde_json::to_string(event) {
50            // Ignore send errors — no subscribers is fine
51            let _ = self.sender.send(json);
52        }
53    }
54
55    /// Subscribe to events. Returns a receiver for consuming events.
56    pub fn subscribe(&self) -> broadcast::Receiver<String> {
57        self.sender.subscribe()
58    }
59
60    /// Get the current number of subscribers.
61    #[must_use]
62    pub fn subscriber_count(&self) -> usize {
63        self.sender.receiver_count()
64    }
65}
66
67impl Default for EventBus {
68    fn default() -> Self {
69        Self::new(256)
70    }
71}