use super::{live::LseSubscriber, transformer::LseTransformer};
use crate::{
Identifier, MarketStream, SnapshotFetcher, distribute_messages_to_exchange,
error::DataError,
event::{MarketEvent, MarketIter},
exchange::Connector,
instrument::InstrumentData,
process_buffered_events, schedule_pings_to_exchange,
subscriber::{Subscribed, Subscriber},
subscription::{Subscription, SubscriptionKind},
};
use futures::{Stream, StreamExt};
use rustrade_instrument::exchange::ExchangeId;
use rustrade_integration::{
protocol::websocket::{WebSocketSerdeParser, WsStream},
stream::ExchangeStream,
};
use std::{
pin::Pin,
task::{Context, Poll},
};
use tokio::sync::mpsc;
#[derive(Debug)]
pub struct LseStream<Exchange, InstrumentKey, Kind>
where
Exchange: Connector,
InstrumentKey: Clone,
Kind: SubscriptionKind,
MarketIter<InstrumentKey, Kind::Event>:
From<(ExchangeId, InstrumentKey, super::tick::LseMessage)>,
{
inner: ExchangeStream<
WebSocketSerdeParser,
WsStream,
LseTransformer<Exchange, InstrumentKey, Kind>,
>,
}
impl<Exchange, InstrumentKey, Kind> Stream for LseStream<Exchange, InstrumentKey, Kind>
where
Exchange: Connector,
InstrumentKey: Clone,
Kind: SubscriptionKind,
MarketIter<InstrumentKey, Kind::Event>:
From<(ExchangeId, InstrumentKey, super::tick::LseMessage)>,
{
type Item = Result<MarketEvent<InstrumentKey, Kind::Event>, DataError>;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
Pin::new(&mut self.get_mut().inner).poll_next(cx)
}
}
impl<Exchange, Instrument, Kind> MarketStream<Exchange, Instrument, Kind>
for LseStream<Exchange, Instrument::Key, Kind>
where
Exchange: Connector<Subscriber = LseSubscriber> + Send + Sync,
Instrument: InstrumentData,
Kind: SubscriptionKind + Send + Sync,
Kind::Event: Send + Sync,
MarketIter<Instrument::Key, Kind::Event>:
From<(ExchangeId, Instrument::Key, super::tick::LseMessage)>,
{
async fn init<SnapFetcher>(
subscriber: &Exchange::Subscriber,
subscriptions: &[Subscription<Exchange, Instrument, Kind>],
) -> Result<Self, DataError>
where
SnapFetcher: SnapshotFetcher<Exchange, Kind>,
Subscription<Exchange, Instrument, Kind>:
Identifier<Exchange::Channel> + Identifier<Exchange::Market>,
{
let Subscribed {
websocket,
map: instrument_map,
buffered_websocket_events,
} = subscriber.subscribe(subscriptions).await?;
let initial_snapshots = SnapFetcher::fetch_snapshots(subscriptions).await?;
let (ws_sink, ws_stream) = websocket.split();
let (ws_sink_tx, ws_sink_rx) = mpsc::unbounded_channel();
tokio::spawn(distribute_messages_to_exchange(
Exchange::ID,
ws_sink,
ws_sink_rx,
));
if let Some(ping_interval) = Exchange::ping_interval() {
tokio::spawn(schedule_pings_to_exchange(
Exchange::ID,
ws_sink_tx.clone(),
ping_interval,
));
}
let resume = subscriber.resume_state().zip(
subscriptions
.first()
.map(|subscription| subscription.kind.as_str()),
);
let mut transformer =
LseTransformer::new(instrument_map, &initial_snapshots, ws_sink_tx, resume).await?;
let mut processed = process_buffered_events::<WebSocketSerdeParser, _>(
&mut transformer,
buffered_websocket_events,
);
processed.extend(initial_snapshots.into_iter().map(Ok));
Ok(Self {
inner: ExchangeStream::new(ws_stream, transformer, processed),
})
}
}