use std::future::Future;
use std::sync::Arc;
use std::sync::atomic::Ordering;
use tokio::net::TcpListener;
use super::{Connections, WebSocketDispatcher};
use crate::serve::ServeReport;
impl WebSocketDispatcher {
pub async fn serve_with_shutdown(
self: Arc<Self>,
listener: TcpListener,
shutdown: impl Future<Output = ()> + Send,
) -> ServeReport {
trace_info!(
addr = %listener
.local_addr()
.unwrap_or_else(|_| std::net::SocketAddr::from(([0, 0, 0, 0], 0))),
"A2A WebSocket server listening (graceful)"
);
let conns = Connections::default();
let handler = Arc::clone(&self.handler);
let (completion, grace, drain) =
(self.completion_grace, self.task_grace, self.drain_timeout);
Arc::clone(&self)
.accept_loop(listener, shutdown, &conns)
.await;
let tasks = handler.finish_in_flight(completion, grace).await;
conns.closing.cancel();
conns.tracker.close();
let drained = tokio::time::timeout(drain, conns.tracker.wait())
.await
.is_ok();
let abandoned = if drained { 0 } else { conns.tracker.len() };
ServeReport {
accepted: conns.accepted.load(Ordering::Relaxed),
drained,
abandoned,
tasks: Some(tasks),
}
}
}