cookie_agent_server/service/
mod.rs1mod routes;
2mod runtime_notifications;
3mod subscriptions;
4mod websocket;
5
6use std::{io, net::SocketAddr, sync::Arc};
7
8use cookie_agent_engine::Engine;
9use cookie_agent_protocol::{MessageStream, TransportError};
10use thiserror::Error;
11use tokio::task::JoinHandle;
12use tokio_util::sync::CancellationToken;
13
14#[derive(Clone)]
16pub struct Server {
17 pub(crate) engine: Engine,
18 pub(crate) shutdown: CancellationToken,
19}
20
21impl Server {
22 #[must_use]
23 pub fn new(engine: Engine) -> Self {
24 Self {
25 engine,
26 shutdown: CancellationToken::new(),
27 }
28 }
29
30 pub fn shutdown(&self) {
31 self.shutdown.cancel();
32 }
33
34 pub async fn serve_stream<S>(self: Arc<Self>, stream: S) -> Result<(), TransportError>
35 where
36 S: MessageStream,
37 {
38 let connection_shutdown = self.shutdown.child_token();
39 cookie_agent_protocol::serve(self, stream, connection_shutdown).await
40 }
41}
42
43pub struct RunningServer {
44 pub(super) address: SocketAddr,
45 pub(super) task: JoinHandle<()>,
46}
47
48impl RunningServer {
49 #[must_use]
50 pub const fn address(&self) -> SocketAddr {
51 self.address
52 }
53
54 pub async fn wait(self) {
55 let _ = self.task.await;
56 }
57}
58
59#[derive(Debug, Error)]
60pub enum ServerError {
61 #[error("could not bind localhost websocket listener: {0}")]
62 Listen(#[source] io::Error),
63}