Let-chains require Rust 1.87+ (stabilized May 2025). Added rust-version field to document the MSRV so cargo warns on older toolchains.
76 lines
2.2 KiB
Rust
76 lines
2.2 KiB
Rust
use axum::{
|
|
extract::{
|
|
State,
|
|
ws::{Message, WebSocket, WebSocketUpgrade},
|
|
},
|
|
response::IntoResponse,
|
|
};
|
|
use serde_json;
|
|
use tracing::info;
|
|
|
|
use super::DashboardState;
|
|
|
|
// WebSocket handler
|
|
pub(super) async fn handle_websocket(ws: WebSocketUpgrade, State(state): State<DashboardState>) -> impl IntoResponse {
|
|
ws.on_upgrade(|socket| handle_websocket_connection(socket, state))
|
|
}
|
|
|
|
pub(super) async fn handle_websocket_connection(mut socket: WebSocket, state: DashboardState) {
|
|
info!("WebSocket connection established");
|
|
|
|
// Subscribe to events from the global bus
|
|
let mut rx = state.app_state.dashboard_tx.subscribe();
|
|
|
|
// Send initial connection message
|
|
let _ = socket
|
|
.send(Message::Text(
|
|
serde_json::json!({
|
|
"type": "connected",
|
|
"message": "Connected to LLM Proxy Dashboard"
|
|
})
|
|
.to_string()
|
|
.into(),
|
|
))
|
|
.await;
|
|
|
|
// Handle incoming messages and broadcast events
|
|
loop {
|
|
tokio::select! {
|
|
// Receive broadcast events
|
|
Ok(event) = rx.recv() => {
|
|
let Ok(json_str) = serde_json::to_string(&event) else {
|
|
continue;
|
|
};
|
|
let message = Message::Text(json_str.into());
|
|
if socket.send(message).await.is_err() {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Receive WebSocket messages
|
|
result = socket.recv() => {
|
|
match result {
|
|
Some(Ok(Message::Text(text))) => {
|
|
handle_websocket_message(&text, &state).await;
|
|
}
|
|
_ => break,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
info!("WebSocket connection closed");
|
|
}
|
|
|
|
pub(super) async fn handle_websocket_message(text: &str, state: &DashboardState) {
|
|
// Parse and handle WebSocket messages
|
|
if let Ok(data) = serde_json::from_str::<serde_json::Value>(text)
|
|
&& data.get("type").and_then(|v| v.as_str()) == Some("ping")
|
|
{
|
|
let _ = state.app_state.dashboard_tx.send(serde_json::json!({
|
|
"type": "pong",
|
|
"payload": {}
|
|
}));
|
|
}
|
|
}
|