Refactor threads to use trait implementations
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
@@ -4,6 +4,7 @@ use crate::{
|
||||
database,
|
||||
types::{alpaca::websocket, Asset},
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use futures_util::{stream::SplitSink, SinkExt};
|
||||
use log::info;
|
||||
use serde_json::to_string;
|
||||
@@ -42,23 +43,23 @@ impl Message {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait Handler: Send + Sync {
|
||||
async fn add_assets(&self, assets: Vec<Asset>, symbols: Vec<String>);
|
||||
async fn remove_assets(&self, assets: Vec<Asset>, symbols: Vec<String>);
|
||||
}
|
||||
|
||||
pub async fn run(
|
||||
app_config: Arc<Config>,
|
||||
thread_type: ThreadType,
|
||||
handler: Arc<Box<dyn Handler>>,
|
||||
guard: Arc<RwLock<Guard>>,
|
||||
mut asset_status_receiver: mpsc::Receiver<Message>,
|
||||
websocket_sender: Arc<
|
||||
Mutex<SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, tungstenite::Message>>,
|
||||
>,
|
||||
mut receiver: mpsc::Receiver<Message>,
|
||||
) {
|
||||
loop {
|
||||
let message = asset_status_receiver.recv().await.unwrap();
|
||||
let message = receiver.recv().await.unwrap();
|
||||
|
||||
spawn(handle_asset_status_message(
|
||||
app_config.clone(),
|
||||
thread_type,
|
||||
handler.clone(),
|
||||
guard.clone(),
|
||||
websocket_sender.clone(),
|
||||
message,
|
||||
));
|
||||
}
|
||||
@@ -66,12 +67,8 @@ pub async fn run(
|
||||
|
||||
#[allow(clippy::significant_drop_tightening)]
|
||||
async fn handle_asset_status_message(
|
||||
app_config: Arc<Config>,
|
||||
thread_type: ThreadType,
|
||||
handler: Arc<Box<dyn Handler>>,
|
||||
guard: Arc<RwLock<Guard>>,
|
||||
websocket_sender: Arc<
|
||||
Mutex<SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, tungstenite::Message>>,
|
||||
>,
|
||||
message: Message,
|
||||
) {
|
||||
let symbols = message
|
||||
@@ -93,37 +90,7 @@ async fn handle_asset_status_message(
|
||||
);
|
||||
guard.pending_subscriptions.extend(message.assets.clone());
|
||||
|
||||
info!("{:?} - Added {:?}.", thread_type, symbols);
|
||||
|
||||
let database_future = async {
|
||||
if matches!(thread_type, ThreadType::Bars(_)) {
|
||||
database::assets::upsert_batch(&app_config.clickhouse_client, message.assets)
|
||||
.await;
|
||||
}
|
||||
};
|
||||
|
||||
let websocket_future = async move {
|
||||
websocket_sender
|
||||
.lock()
|
||||
.await
|
||||
.send(tungstenite::Message::Text(
|
||||
to_string(&websocket::outgoing::Message::Subscribe(
|
||||
match thread_type {
|
||||
ThreadType::Bars(_) => {
|
||||
websocket::outgoing::subscribe::Message::new_market(symbols)
|
||||
}
|
||||
ThreadType::News => {
|
||||
websocket::outgoing::subscribe::Message::new_news(symbols)
|
||||
}
|
||||
},
|
||||
))
|
||||
.unwrap(),
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
};
|
||||
|
||||
join!(database_future, websocket_future);
|
||||
handler.add_assets(message.assets, symbols).await;
|
||||
}
|
||||
Action::Remove => {
|
||||
let mut guard = guard.write().await;
|
||||
@@ -131,40 +98,121 @@ async fn handle_asset_status_message(
|
||||
guard
|
||||
.assets
|
||||
.retain(|asset, _| !message.assets.contains(asset));
|
||||
guard.pending_unsubscriptions.extend(message.assets);
|
||||
guard.pending_unsubscriptions.extend(message.assets.clone());
|
||||
|
||||
info!("{:?} - Removed {:?}.", thread_type, symbols);
|
||||
|
||||
let sybols_clone = symbols.clone();
|
||||
let database_future = database::assets::delete_where_symbols(
|
||||
&app_config.clickhouse_client,
|
||||
&sybols_clone,
|
||||
);
|
||||
|
||||
let websocket_future = async move {
|
||||
websocket_sender
|
||||
.lock()
|
||||
.await
|
||||
.send(tungstenite::Message::Text(
|
||||
to_string(&websocket::outgoing::Message::Unsubscribe(
|
||||
match thread_type {
|
||||
ThreadType::Bars(_) => {
|
||||
websocket::outgoing::subscribe::Message::new_market(symbols)
|
||||
}
|
||||
ThreadType::News => {
|
||||
websocket::outgoing::subscribe::Message::new_news(symbols)
|
||||
}
|
||||
},
|
||||
))
|
||||
.unwrap(),
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
};
|
||||
|
||||
join!(database_future, websocket_future);
|
||||
handler.remove_assets(message.assets, symbols).await;
|
||||
}
|
||||
}
|
||||
|
||||
message.response.send(()).unwrap();
|
||||
}
|
||||
|
||||
pub fn create_asset_status_handler(
|
||||
thread_type: ThreadType,
|
||||
app_config: Arc<Config>,
|
||||
websocket_sender: Arc<
|
||||
Mutex<SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, tungstenite::Message>>,
|
||||
>,
|
||||
) -> Box<dyn Handler> {
|
||||
match thread_type {
|
||||
ThreadType::Bars(_) => Box::new(BarsHandler {
|
||||
app_config,
|
||||
websocket_sender,
|
||||
}),
|
||||
ThreadType::News => Box::new(NewsHandler { websocket_sender }),
|
||||
}
|
||||
}
|
||||
|
||||
struct BarsHandler {
|
||||
app_config: Arc<Config>,
|
||||
websocket_sender:
|
||||
Arc<Mutex<SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, tungstenite::Message>>>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Handler for BarsHandler {
|
||||
async fn add_assets(&self, assets: Vec<Asset>, symbols: Vec<String>) {
|
||||
let database_future =
|
||||
database::assets::upsert_batch(&self.app_config.clickhouse_client, assets);
|
||||
|
||||
let symbols_clone = symbols.clone();
|
||||
let websocket_future = async move {
|
||||
self.websocket_sender
|
||||
.lock()
|
||||
.await
|
||||
.send(tungstenite::Message::Text(
|
||||
to_string(&websocket::outgoing::Message::Subscribe(
|
||||
websocket::outgoing::subscribe::Message::new_market(symbols_clone),
|
||||
))
|
||||
.unwrap(),
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
};
|
||||
|
||||
join!(database_future, websocket_future);
|
||||
info!("Added {:?}.", symbols);
|
||||
}
|
||||
|
||||
async fn remove_assets(&self, _: Vec<Asset>, symbols: Vec<String>) {
|
||||
let symbols_clone = symbols.clone();
|
||||
let database_future = database::assets::delete_where_symbols(
|
||||
&self.app_config.clickhouse_client,
|
||||
&symbols_clone,
|
||||
);
|
||||
|
||||
let symbols_clone = symbols.clone();
|
||||
let websocket_future = async move {
|
||||
self.websocket_sender
|
||||
.lock()
|
||||
.await
|
||||
.send(tungstenite::Message::Text(
|
||||
to_string(&websocket::outgoing::Message::Unsubscribe(
|
||||
websocket::outgoing::subscribe::Message::new_market(symbols_clone),
|
||||
))
|
||||
.unwrap(),
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
};
|
||||
|
||||
join!(database_future, websocket_future);
|
||||
info!("Removed {:?}.", symbols);
|
||||
}
|
||||
}
|
||||
|
||||
struct NewsHandler {
|
||||
websocket_sender:
|
||||
Arc<Mutex<SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, tungstenite::Message>>>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Handler for NewsHandler {
|
||||
async fn add_assets(&self, _: Vec<Asset>, symbols: Vec<String>) {
|
||||
self.websocket_sender
|
||||
.lock()
|
||||
.await
|
||||
.send(tungstenite::Message::Text(
|
||||
to_string(&websocket::outgoing::Message::Subscribe(
|
||||
websocket::outgoing::subscribe::Message::new_news(symbols),
|
||||
))
|
||||
.unwrap(),
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
async fn remove_assets(&self, _: Vec<Asset>, symbols: Vec<String>) {
|
||||
self.websocket_sender
|
||||
.lock()
|
||||
.await
|
||||
.send(tungstenite::Message::Text(
|
||||
to_string(&websocket::outgoing::Message::Unsubscribe(
|
||||
websocket::outgoing::subscribe::Message::new_news(symbols),
|
||||
))
|
||||
.unwrap(),
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user