use crate::engine::FrameSender;
use crate::error::TransportError;
use crate::packet::{Frame, Handshake};
use crate::polling::PollingClient;
use crate::websocket::{WebSocketConnector, WebSocketStream};
use tokio::sync::{mpsc, oneshot};
use tokio_util::sync::CancellationToken;
use url::Url;
#[derive(Debug, Default)]
pub enum TransportStrategy {
#[default]
Polling,
WebSocket,
}
impl TransportStrategy {
#[allow(clippy::too_many_arguments)]
pub async fn run<C>(
self,
base_url: Url,
http_client: reqwest::Client,
connector: C,
handshake_tx: oneshot::Sender<Handshake>,
frame_tx: FrameSender,
transport_rx: mpsc::Receiver<Frame>,
token: CancellationToken,
) -> Result<(), TransportError>
where
C: WebSocketConnector + Send + 'static,
{
match self {
TransportStrategy::Polling => {
PollingClient(http_client)
.transport(
base_url,
connector,
handshake_tx,
frame_tx,
transport_rx,
token,
)
.await
}
TransportStrategy::WebSocket => {
let stream = WebSocketStream::connect(base_url, None, connector).await?;
stream
.transport(Some(handshake_tx), frame_tx, transport_rx)
.await?;
Ok(())
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::engine::FrameSender;
use crate::error::TransportError;
use tokio::sync::{mpsc, oneshot};
use tokio_tungstenite::tungstenite::Error as TungsteniteError;
use url::Url;
#[test]
fn transport_strategy_default_is_polling() {
assert!(matches!(
TransportStrategy::default(),
TransportStrategy::Polling
));
}
#[tokio::test]
async fn websocket_strategy_propagates_connector_error() {
let base_url = Url::parse("ws://127.0.0.1:1/").unwrap();
let http_client = reqwest::Client::new();
let connector = async |_| Err(TungsteniteError::ConnectionClosed);
let (handshake_tx, _handshake_rx) = oneshot::channel();
let (engine_tx, _engine_rx) = mpsc::channel(1);
let frame_tx = FrameSender(engine_tx);
let (_transport_tx, transport_rx) = mpsc::channel(1);
let token = CancellationToken::new();
let result = TransportStrategy::WebSocket
.run(
base_url,
http_client,
connector,
handshake_tx,
frame_tx,
transport_rx,
token,
)
.await;
assert!(matches!(result, Err(TransportError::WebSocket(_))));
}
}