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