use std::collections::HashMap; use std::sync::Mutex; use tokio::sync::mpsc; /// A fired timer event delivered to the plugin that created it. #[derive(Clone, Debug)] pub struct TimerEvent { pub timer_id: String, pub callback_id: String, } /// Manages per-plugin event channels for timer callbacks. pub struct CallbackBus { senders: Mutex>>, } impl CallbackBus { pub fn new() -> Self { Self { senders: Mutex::new(HashMap::new()), } } /// Register a plugin and get a receiver for its timer events. pub fn subscribe(&self, plugin_id: &str) -> mpsc::Receiver { let (tx, rx) = mpsc::channel(64); self.senders .lock() .unwrap() .insert(plugin_id.to_string(), tx); rx } /// Deliver a timer event to the target plugin. pub fn fire(&self, plugin_id: &str, event: TimerEvent) { let senders = self.senders.lock().unwrap(); if let Some(tx) = senders.get(plugin_id) { // Non-blocking send; drop if channel full let _ = tx.try_send(event); } } /// Remove a plugin's channel (on unregister/disconnect). pub fn remove(&self, plugin_id: &str) { self.senders.lock().unwrap().remove(plugin_id); } }