This repository has been archived by the owner on Aug 7, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- using tokio-tungstenite to achieve the async WebSocket goal - refactoring blocking and async WebSocket worker interface - adding a new feature **async-websocket**
- Loading branch information
Showing
14 changed files
with
678 additions
and
261 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
use fugle::websocket::IntradayBuilder; | ||
|
||
#[tokio::main] | ||
async fn main() { | ||
let mut ws = IntradayBuilder::new().symbol_id("2884").odd_lot().build(); | ||
|
||
println!("{:?}", ws.async_chart().await.unwrap().recv().await); | ||
println!("{:?}", ws.async_meta().await.unwrap().recv().await); | ||
println!("{:?}", ws.async_quote().await.unwrap().recv().await); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
use fugle::websocket::IntradayBuilder; | ||
|
||
fn main() { | ||
let mut ws = IntradayBuilder::new().symbol_id("2884").odd_lot().build(); | ||
|
||
println!("{:?}", ws.chart().unwrap().recv().unwrap()); | ||
println!("{:?}", ws.meta().unwrap().recv().unwrap()); | ||
println!("{:?}", ws.quote().unwrap().recv().unwrap()); | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
use std::sync::{ | ||
atomic::{AtomicBool, Ordering}, | ||
Arc, | ||
}; | ||
|
||
use futures_util::StreamExt; | ||
use log::error; | ||
use tokio::sync::mpsc::UnboundedSender; | ||
use tokio_tungstenite::connect_async; | ||
|
||
use crate::schema::Result; | ||
|
||
pub(crate) struct Async { | ||
pub(crate) routine: Option<tokio::task::JoinHandle<()>>, | ||
} | ||
|
||
impl Async { | ||
pub(crate) async fn new<T>( | ||
uri: &str, | ||
sender: UnboundedSender<T>, | ||
done: Arc<AtomicBool>, | ||
) -> Result<Async> | ||
where | ||
T: for<'de> serde::Deserialize<'de> + Send + 'static, | ||
{ | ||
let (mut socket, _) = connect_async(uri).await?; | ||
|
||
let routine = tokio::spawn(async move { | ||
while !done.load(Ordering::SeqCst) { | ||
if let Some(Ok(msg)) = socket.next().await { | ||
if let Ok(m) = msg.to_text() { | ||
if let Ok(m) = serde_json::from_str(m) { | ||
if let Err(e) = sender.send(m) { | ||
error!("{}", e); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
let _ = socket.close(None).await; | ||
}); | ||
|
||
Ok(Async { | ||
routine: Some(routine), | ||
}) | ||
} | ||
} | ||
|
||
impl super::Worker for Async { | ||
fn stop(&mut self) { | ||
if let Some(routine) = self.routine.take() { | ||
drop(routine) | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use tokio::{ | ||
sync::mpsc::unbounded_channel, | ||
time::{sleep, Duration}, | ||
}; | ||
|
||
use super::{ | ||
super::{QuoteResponse, Worker, INTRADAY_QUOTE}, | ||
*, | ||
}; | ||
|
||
#[tokio::test] | ||
async fn test_async_worker_stop() { | ||
let (tx, _) = unbounded_channel::<QuoteResponse>(); | ||
let done = Arc::new(AtomicBool::new(false)); | ||
let mut worker = Async::new( | ||
&format!("{}?symbolId=2884&apiToken=demo", INTRADAY_QUOTE), | ||
tx, | ||
done.clone(), | ||
) | ||
.await | ||
.unwrap(); | ||
|
||
done.store(true, Ordering::SeqCst); | ||
sleep(Duration::from_millis(3)).await; | ||
|
||
worker.stop(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
use std::{ | ||
sync::{ | ||
atomic::{AtomicBool, Ordering}, | ||
mpsc::Sender, | ||
Arc, | ||
}, | ||
thread, | ||
}; | ||
|
||
use log::error; | ||
use tungstenite::connect; | ||
|
||
use crate::schema::Result; | ||
|
||
pub(crate) struct Block { | ||
pub(crate) thread: Option<thread::JoinHandle<()>>, | ||
} | ||
|
||
impl Block { | ||
pub(crate) fn new<T>(uri: &str, sender: Sender<T>, done: Arc<AtomicBool>) -> Result<Block> | ||
where | ||
T: for<'de> serde::Deserialize<'de> + Send + 'static, | ||
{ | ||
let (mut socket, _) = connect(uri)?; | ||
|
||
let thread = thread::spawn(move || { | ||
while !done.load(Ordering::SeqCst) { | ||
if let Ok(msg) = socket.read_message() { | ||
if let Ok(m) = msg.to_text() { | ||
if let Ok(m) = serde_json::from_str(m) { | ||
if let Err(e) = sender.send(m) { | ||
error!("{}", e); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
let _ = socket.close(None); | ||
}); | ||
|
||
Ok(Block { | ||
thread: Some(thread), | ||
}) | ||
} | ||
} | ||
|
||
impl super::Worker for Block { | ||
fn stop(&mut self) { | ||
if let Some(thread) = self.thread.take() { | ||
let _ = thread.join(); | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use std::{sync::mpsc::channel, thread::sleep, time::Duration}; | ||
|
||
use super::{ | ||
super::{QuoteResponse, Worker, INTRADAY_QUOTE}, | ||
*, | ||
}; | ||
|
||
#[test] | ||
fn test_block_worker_stop() { | ||
let (tx, _) = channel::<QuoteResponse>(); | ||
let done = Arc::new(AtomicBool::new(false)); | ||
let mut worker = Block::new( | ||
&format!("{}?symbolId=2884&apiToken=demo", INTRADAY_QUOTE), | ||
tx, | ||
done.clone(), | ||
) | ||
.unwrap(); | ||
|
||
done.store(true, Ordering::SeqCst); | ||
sleep(Duration::from_millis(3)); | ||
|
||
worker.stop(); | ||
} | ||
} |
Oops, something went wrong.