rivetkit_client/drivers/
ws.rs1use anyhow::{Context, Result};
2use futures_util::{SinkExt, StreamExt};
3use std::sync::Arc;
4use tokio::sync::mpsc;
5use tokio_tungstenite::tungstenite::Message;
6use tracing::debug;
7
8use crate::{
9 protocol::{codec, to_client, to_server},
10 EncodingKind,
11};
12
13use super::{
14 DriverConnectArgs, DriverConnection, DriverHandle, DriverStopReason, MessageToClient,
15 MessageToServer,
16};
17
18pub(crate) async fn connect(args: DriverConnectArgs) -> Result<DriverConnection> {
19 let target = args.remote_manager.gateway_target(&args.query).await?;
21
22 debug!(?target, "opening WebSocket connection to actor via gateway");
23
24 let ws = args
26 .remote_manager
27 .open_websocket(
28 &target,
29 args.encoding_kind,
30 args.parameters,
31 args.conn_id,
32 args.conn_token,
33 )
34 .await
35 .context("Failed to connect to WebSocket via gateway")?;
36
37 let (in_tx, in_rx) = mpsc::unbounded_channel::<MessageToClient>();
38 let (out_tx, out_rx) = mpsc::unbounded_channel::<MessageToServer>();
39
40 let task = tokio::spawn(start(ws, args.encoding_kind, in_tx, out_rx));
41 let handle = DriverHandle::new(out_tx, task.abort_handle());
42
43 Ok((handle, in_rx, task))
44}
45
46async fn start(
47 ws: tokio_tungstenite::WebSocketStream<
48 tokio_tungstenite::MaybeTlsStream<tokio::net::TcpStream>,
49 >,
50 encoding_kind: EncodingKind,
51 in_tx: mpsc::UnboundedSender<MessageToClient>,
52 mut out_rx: mpsc::UnboundedReceiver<MessageToServer>,
53) -> DriverStopReason {
54 let (mut ws_sink, mut ws_stream) = ws.split();
55
56 let serialize = get_msg_serializer(encoding_kind);
57 let deserialize = get_msg_deserializer(encoding_kind);
58
59 loop {
60 tokio::select! {
61 msg = out_rx.recv() => {
63 let Some(msg) = msg else {
65 debug!("Sender dropped");
66 return DriverStopReason::UserAborted;
67 };
68
69 let msg = match serialize(&msg) {
70 Ok(msg) => msg,
71 Err(e) => {
72 debug!("Failed to serialize message: {:?}", e);
73 continue;
74 }
75 };
76
77 if let Err(e) = ws_sink.send(msg).await {
78 debug!("Failed to send message: {:?}", e);
79 continue;
80 }
81 },
82 msg = ws_stream.next() => {
84 let Some(msg) = msg else {
85 debug!("Receiver dropped");
86 return DriverStopReason::ServerDisconnect;
87 };
88
89 match msg {
90 Ok(msg) => match msg {
91 Message::Text(_) | Message::Binary(_) => {
92 let Ok(msg) = deserialize(&msg) else {
93 debug!("Failed to parse message: {:?}", msg);
94 continue;
95 };
96
97 if let Err(e) = in_tx.send(Arc::new(msg)) {
98 debug!("Failed to send text message: {}", e);
99 return DriverStopReason::UserAborted;
101 }
102 },
103 Message::Close(_) => {
104 debug!("Close message");
105 return DriverStopReason::ServerDisconnect;
106 },
107 _ => {
108 debug!("Invalid message type received");
109 }
110 }
111 Err(e) => {
112 debug!("WebSocket error: {}", e);
113 return DriverStopReason::ServerError;
114 }
115 }
116 }
117 }
118 }
119}
120
121fn get_msg_deserializer(
122 encoding_kind: EncodingKind,
123) -> fn(&Message) -> Result<to_client::ToClient> {
124 match encoding_kind {
125 EncodingKind::Json => json_msg_deserialize,
126 EncodingKind::Cbor => cbor_msg_deserialize,
127 EncodingKind::Bare => bare_msg_deserialize,
128 }
129}
130
131fn get_msg_serializer(encoding_kind: EncodingKind) -> fn(&to_server::ToServer) -> Result<Message> {
132 match encoding_kind {
133 EncodingKind::Json => json_msg_serialize,
134 EncodingKind::Cbor => cbor_msg_serialize,
135 EncodingKind::Bare => bare_msg_serialize,
136 }
137}
138
139fn json_msg_deserialize(value: &Message) -> Result<to_client::ToClient> {
140 match value {
141 Message::Text(text) => codec::decode_to_client(EncodingKind::Json, text.as_bytes()),
142 Message::Binary(bin) => codec::decode_to_client(EncodingKind::Json, bin),
143 _ => Err(anyhow::anyhow!("Invalid message type")),
144 }
145}
146
147fn cbor_msg_deserialize(value: &Message) -> Result<to_client::ToClient> {
148 match value {
149 Message::Binary(bin) => codec::decode_to_client(EncodingKind::Cbor, bin),
150 Message::Text(text) => codec::decode_to_client(EncodingKind::Cbor, text.as_bytes()),
151 _ => Err(anyhow::anyhow!("Invalid message type")),
152 }
153}
154
155fn json_msg_serialize(value: &to_server::ToServer) -> Result<Message> {
156 let payload = codec::encode_to_server(EncodingKind::Json, value)?;
157 Ok(Message::Text(String::from_utf8(payload)?.into()))
158}
159
160fn cbor_msg_serialize(value: &to_server::ToServer) -> Result<Message> {
161 Ok(Message::Binary(
162 codec::encode_to_server(EncodingKind::Cbor, value)?.into(),
163 ))
164}
165
166fn bare_msg_deserialize(value: &Message) -> Result<to_client::ToClient> {
167 match value {
168 Message::Binary(bin) => codec::decode_to_client(EncodingKind::Bare, bin),
169 Message::Text(text) => codec::decode_to_client(EncodingKind::Bare, text.as_bytes()),
170 _ => Err(anyhow::anyhow!("Invalid message type")),
171 }
172}
173
174fn bare_msg_serialize(value: &to_server::ToServer) -> Result<Message> {
175 Ok(Message::Binary(
176 codec::encode_to_server(EncodingKind::Bare, value)?.into(),
177 ))
178}