//! Tauri 事件发射器 //! 将实时事件发送到前端的服务 use anyhow::Result; use std::sync::Arc; use tauri::{AppHandle, Manager}; use tokio::sync::broadcast; use tracing::{info, warn, error, debug}; use serde::{Serialize, Deserialize}; use crate::business::services::realtime_monitor_v2::{RealtimeEventV2, EventSubscriber}; /// Tauri 事件名称常量 pub mod events { pub const COMFYUI_CONNECTION_CHANGED: &str = "comfyui://connection-changed"; pub const COMFYUI_EXECUTION_STARTED: &str = "comfyui://execution-started"; pub const COMFYUI_EXECUTION_PROGRESS: &str = "comfyui://execution-progress"; pub const COMFYUI_NODE_EXECUTING: &str = "comfyui://node-executing"; pub const COMFYUI_EXECUTION_COMPLETED: &str = "comfyui://execution-completed"; pub const COMFYUI_EXECUTION_FAILED: &str = "comfyui://execution-failed"; pub const COMFYUI_QUEUE_UPDATED: &str = "comfyui://queue-updated"; pub const COMFYUI_SYSTEM_STATUS_UPDATED: &str = "comfyui://system-status-updated"; } /// 前端事件数据结构 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct FrontendEvent { pub event_type: String, pub data: serde_json::Value, pub timestamp: String, } /// Tauri 事件发射器 pub struct TauriEventEmitter { app_handle: AppHandle, event_receiver: Option>, is_running: Arc>, task_handle: Arc>>>, } impl TauriEventEmitter { /// 创建新的事件发射器 pub fn new(app_handle: AppHandle) -> Self { Self { app_handle, event_receiver: None, is_running: Arc::new(tokio::sync::RwLock::new(false)), task_handle: Arc::new(tokio::sync::RwLock::new(None)), } } /// 启动事件发射器 pub async fn start(&mut self, mut event_receiver: broadcast::Receiver) -> Result<()> { info!("启动 Tauri 事件发射器"); // 检查是否已经在运行 { let running = self.is_running.read().await; if *running { return Ok(()); } } let app_handle = self.app_handle.clone(); let is_running = Arc::clone(&self.is_running); // 启动事件处理任务 let handle = tokio::spawn(async move { { let mut running = is_running.write().await; *running = true; } info!("Tauri 事件发射器已启动"); while let Ok(event) = event_receiver.recv().await { if let Err(e) = Self::emit_to_frontend(&app_handle, &event).await { error!("发送事件到前端失败: {}", e); } } { let mut running = is_running.write().await; *running = false; } info!("Tauri 事件发射器已停止"); }); { let mut task_handle = self.task_handle.write().await; *task_handle = Some(handle); } Ok(()) } /// 停止事件发射器 pub async fn stop(&self) -> Result<()> { info!("停止 Tauri 事件发射器"); let handle = { let mut task_handle = self.task_handle.write().await; task_handle.take() }; if let Some(handle) = handle { handle.abort(); } { let mut running = self.is_running.write().await; *running = false; } Ok(()) } /// 检查是否正在运行 pub async fn is_running(&self) -> bool { *self.is_running.read().await } /// 发送事件到前端 async fn emit_to_frontend(app_handle: &AppHandle, event: &RealtimeEventV2) -> Result<()> { let (event_name, event_data) = Self::convert_event_for_frontend(event); let frontend_event = FrontendEvent { event_type: event_name.clone(), data: event_data, timestamp: chrono::Utc::now().to_rfc3339(), }; // 发送到前端 app_handle.emit_all(&event_name, &frontend_event) .map_err(|e| anyhow::anyhow!("发送事件失败: {}", e))?; debug!("已发送事件到前端: {}", event_name); Ok(()) } /// 转换事件为前端格式 fn convert_event_for_frontend(event: &RealtimeEventV2) -> (String, serde_json::Value) { match event { RealtimeEventV2::ConnectionChanged { connected, message, timestamp } => ( events::COMFYUI_CONNECTION_CHANGED.to_string(), serde_json::json!({ "connected": connected, "message": message, "timestamp": timestamp }) ), RealtimeEventV2::ExecutionStarted { prompt_id, execution_id, node_id, timestamp } => ( events::COMFYUI_EXECUTION_STARTED.to_string(), serde_json::json!({ "prompt_id": prompt_id, "execution_id": execution_id, "node_id": node_id, "timestamp": timestamp }) ), RealtimeEventV2::ExecutionProgress { prompt_id, execution_id, node_id, progress, max_progress, percentage, timestamp } => ( events::COMFYUI_EXECUTION_PROGRESS.to_string(), serde_json::json!({ "prompt_id": prompt_id, "execution_id": execution_id, "node_id": node_id, "progress": progress, "max_progress": max_progress, "percentage": percentage, "timestamp": timestamp }) ), RealtimeEventV2::NodeExecuting { prompt_id, execution_id, node_id, node_title, timestamp } => ( events::COMFYUI_NODE_EXECUTING.to_string(), serde_json::json!({ "prompt_id": prompt_id, "execution_id": execution_id, "node_id": node_id, "node_title": node_title, "timestamp": timestamp }) ), RealtimeEventV2::ExecutionCompleted { prompt_id, execution_id, outputs, output_urls, execution_time, timestamp } => ( events::COMFYUI_EXECUTION_COMPLETED.to_string(), serde_json::json!({ "prompt_id": prompt_id, "execution_id": execution_id, "outputs": outputs, "output_urls": output_urls, "execution_time": execution_time, "timestamp": timestamp }) ), RealtimeEventV2::ExecutionFailed { prompt_id, execution_id, node_id, error, details, timestamp } => ( events::COMFYUI_EXECUTION_FAILED.to_string(), serde_json::json!({ "prompt_id": prompt_id, "execution_id": execution_id, "node_id": node_id, "error": error, "details": details, "timestamp": timestamp }) ), RealtimeEventV2::QueueUpdated { running_count, pending_count, timestamp } => ( events::COMFYUI_QUEUE_UPDATED.to_string(), serde_json::json!({ "running_count": running_count, "pending_count": pending_count, "timestamp": timestamp }) ), RealtimeEventV2::SystemStatusUpdated { memory_usage, gpu_usage, active_connections, timestamp } => ( events::COMFYUI_SYSTEM_STATUS_UPDATED.to_string(), serde_json::json!({ "memory_usage": memory_usage, "gpu_usage": gpu_usage, "active_connections": active_connections, "timestamp": timestamp }) ), } } } impl EventSubscriber for TauriEventEmitter { fn handle_event(&self, event: &RealtimeEventV2) { let app_handle = self.app_handle.clone(); let event = event.clone(); // 异步发送事件 tokio::spawn(async move { if let Err(e) = Self::emit_to_frontend(&app_handle, &event).await { error!("发送事件到前端失败: {}", e); } }); } } /// 事件发射器管理器 pub struct EventEmitterManager { emitters: Vec>, } impl EventEmitterManager { /// 创建新的管理器 pub fn new() -> Self { Self { emitters: Vec::new(), } } /// 添加发射器 pub fn add_emitter(&mut self, emitter: Arc) { self.emitters.push(emitter); } /// 启动所有发射器 pub async fn start_all(&mut self, event_receiver: broadcast::Receiver) -> Result<()> { for emitter in &mut self.emitters { // 为每个发射器创建独立的接收器 let receiver = event_receiver.resubscribe(); // 注意:这里需要获取可变引用,但 Arc 不允许 // 实际实现中可能需要重新设计架构 } Ok(()) } /// 停止所有发射器 pub async fn stop_all(&self) -> Result<()> { for emitter in &self.emitters { emitter.stop().await?; } Ok(()) } }