use std::time::Duration;
use anyhow::Error;
use futures::{AsyncRead, AsyncWrite};
use soketto::Sender;
use tokio::time::timeout;
use tracing::{debug, warn};
const SEND_TIMEOUT: Duration = Duration::from_secs(10);
pub fn handle_websocket_error(err: Error) {
if let Some(soketto_err) = err.downcast_ref::<soketto::connection::Error>() {
match soketto_err {
soketto::connection::Error::Closed => {
debug!("connection to client was closed")
}
soketto::connection::Error::Io(soketto_io_err) => {
if soketto_io_err.kind() == std::io::ErrorKind::ConnectionReset {
debug!("Client disconnected WebSocket connection");
} else {
warn!("Websocket IO error: {:?}", soketto_io_err);
}
}
_ => {
warn!("error while handling connection: {:?}", err.to_string())
}
}
} else {
warn!("error while handling connection: {:?}", err.to_string());
}
}
pub async fn send_text<T: AsyncRead + AsyncWrite + Unpin>(
sender: &mut Sender<T>,
text: &str,
) -> anyhow::Result<()> {
timeout(SEND_TIMEOUT, async {
sender.send_text(text).await?;
sender.flush().await?;
anyhow::Ok(())
})
.await?
}
pub async fn send_text_no_flush<T: AsyncRead + AsyncWrite + Unpin>(
sender: &mut Sender<T>,
text: &str,
) -> anyhow::Result<()> {
timeout(SEND_TIMEOUT, async {
sender.send_text(text).await?;
anyhow::Ok(())
})
.await?
}
pub async fn flush<T: AsyncRead + AsyncWrite + Unpin>(
sender: &mut Sender<T>,
) -> anyhow::Result<()> {
timeout(SEND_TIMEOUT, async {
sender.flush().await?;
anyhow::Ok(())
})
.await?
}
pub async fn send_json<T: AsyncRead + AsyncWrite + Unpin, U: serde::Serialize>(
sender: &mut Sender<T>,
value: &U,
) -> anyhow::Result<()> {
send_text(sender, &serde_json::to_string(value)?).await
}