cascade_agent/orchestrator/
server.rs1use super::types::OrchestratorMessage;
2use futures_util::{SinkExt, StreamExt};
3use tokio::net::TcpListener;
4use tokio::sync::{broadcast, mpsc};
5use tokio_tungstenite::accept_async;
6
7pub struct OrchestratorServer {
10 bind_address: String,
11 broadcast_tx: broadcast::Sender<OrchestratorMessage>,
13 inbound_tx: mpsc::Sender<OrchestratorMessage>,
15}
16
17impl OrchestratorServer {
18 pub fn new(
19 bind_address: &str,
20 ) -> (
21 Self,
22 broadcast::Sender<OrchestratorMessage>,
23 mpsc::Receiver<OrchestratorMessage>,
24 ) {
25 let (broadcast_tx, _) = broadcast::channel(256);
26 let (inbound_tx, inbound_rx) = mpsc::channel(256);
27 let server = Self {
28 bind_address: bind_address.to_string(),
29 broadcast_tx: broadcast_tx.clone(),
30 inbound_tx,
31 };
32 (server, broadcast_tx, inbound_rx)
33 }
34
35 pub async fn run(self) -> crate::error::Result<()> {
36 let listener = TcpListener::bind(&self.bind_address).await.map_err(|e| {
37 crate::error::AgentError::OrchestratorError(format!("Failed to bind: {}", e))
38 })?;
39
40 tracing::info!(target: "orchestrator", "Server listening on {}", self.bind_address);
41
42 while let Ok((stream, addr)) = listener.accept().await {
43 let broadcast_tx = self.broadcast_tx.clone();
44 let inbound_tx = self.inbound_tx.clone();
45
46 tokio::spawn(async move {
47 let ws_stream = match accept_async(stream).await {
48 Ok(s) => s,
49 Err(e) => {
50 tracing::error!(target: "orchestrator", "Accept failed from {}: {}", addr, e);
51 return;
52 }
53 };
54
55 tracing::info!(target: "orchestrator", "Orchestrator connected from {}", addr);
56 let (mut ws_sink, mut ws_stream) = ws_stream.split();
57
58 let mut rx = broadcast_tx.subscribe();
60
61 let ws_to_client = async {
63 while let Ok(msg) = rx.recv().await {
64 let json = serde_json::to_string(&msg).unwrap_or_default();
65 if ws_sink
66 .send(tokio_tungstenite::tungstenite::protocol::Message::Text(
67 json.into(),
68 ))
69 .await
70 .is_err()
71 {
72 break;
73 }
74 }
75 };
76
77 let client_to_server = async {
79 while let Some(Ok(msg)) = ws_stream.next().await {
80 if msg.is_text() {
81 let text = msg.to_text().unwrap_or_default();
82 if let Ok(parsed) = serde_json::from_str::<OrchestratorMessage>(text) {
83 if inbound_tx.send(parsed).await.is_err() {
84 break;
85 }
86 }
87 }
88 }
89 };
90
91 tokio::select! {
92 _ = ws_to_client => {},
93 _ = client_to_server => {},
94 }
95
96 tracing::info!(target: "orchestrator", "Orchestrator disconnected from {}", addr);
97 });
98 }
99
100 Ok(())
101 }
102}