|
@@ -11,20 +11,26 @@ use tokio::{
|
|
use tokio_tungstenite::{connect_async, tungstenite::Message};
|
|
use tokio_tungstenite::{connect_async, tungstenite::Message};
|
|
use url::Url;
|
|
use url::Url;
|
|
|
|
|
|
|
|
+/// Relayer object
|
|
#[derive(Debug)]
|
|
#[derive(Debug)]
|
|
-pub struct Client {
|
|
|
|
|
|
+pub struct Relayer {
|
|
|
|
+ /// URL of the relayer
|
|
pub url: String,
|
|
pub url: String,
|
|
|
|
+ /// Sender to the relayer. This can be used to send a Requests to this relayer
|
|
pub send_to_socket: mpsc::Sender<Request>,
|
|
pub send_to_socket: mpsc::Sender<Request>,
|
|
|
|
+ /// Internal receiver. This is used to receive messages from the relayer
|
|
recv_from_socket: broadcast::Receiver<(Response, String)>,
|
|
recv_from_socket: broadcast::Receiver<(Response, String)>,
|
|
|
|
+ /// This sender signals to background connection to stop
|
|
stop_service: oneshot::Sender<()>,
|
|
stop_service: oneshot::Sender<()>,
|
|
}
|
|
}
|
|
|
|
|
|
const NO_ACTIVITY_TIMEOUT_SECS: u64 = 30;
|
|
const NO_ACTIVITY_TIMEOUT_SECS: u64 = 30;
|
|
-const MAX_RECONNECT_ATTEMPTS: u64 = 15;
|
|
|
|
|
|
|
|
-impl Client {
|
|
|
|
|
|
+impl Relayer {
|
|
|
|
+ /// Creates a new relayer
|
|
pub fn new<F>(
|
|
pub fn new<F>(
|
|
sent_messages: Arc<RwLock<Vec<Request>>>,
|
|
sent_messages: Arc<RwLock<Vec<Request>>>,
|
|
|
|
+ connection_retries: u16,
|
|
url: &str,
|
|
url: &str,
|
|
on_connection: Option<F>,
|
|
on_connection: Option<F>,
|
|
) -> Result<Self, Error>
|
|
) -> Result<Self, Error>
|
|
@@ -40,6 +46,7 @@ impl Client {
|
|
send_to_socket.clone(),
|
|
send_to_socket.clone(),
|
|
receiver,
|
|
receiver,
|
|
url,
|
|
url,
|
|
|
|
+ connection_retries,
|
|
on_connection,
|
|
on_connection,
|
|
)?;
|
|
)?;
|
|
|
|
|
|
@@ -56,6 +63,7 @@ impl Client {
|
|
send_to_socket: mpsc::Sender<Request>,
|
|
send_to_socket: mpsc::Sender<Request>,
|
|
mut receiver: mpsc::Receiver<Request>,
|
|
mut receiver: mpsc::Receiver<Request>,
|
|
url_str: &str,
|
|
url_str: &str,
|
|
|
|
+ connection_retries: u16,
|
|
on_connection: Option<F>,
|
|
on_connection: Option<F>,
|
|
) -> Result<(broadcast::Receiver<(Response, String)>, oneshot::Sender<()>), Error>
|
|
) -> Result<(broadcast::Receiver<(Response, String)>, oneshot::Sender<()>), Error>
|
|
where
|
|
where
|
|
@@ -74,7 +82,7 @@ impl Client {
|
|
let mut reconnect = true;
|
|
let mut reconnect = true;
|
|
let mut retries = 0;
|
|
let mut retries = 0;
|
|
|
|
|
|
- while reconnect && retries <= MAX_RECONNECT_ATTEMPTS {
|
|
|
|
|
|
+ while reconnect && retries <= connection_retries {
|
|
log::warn!("{}: Connect attempt {}", url, retries);
|
|
log::warn!("{}: Connect attempt {}", url, retries);
|
|
retries += 1;
|
|
retries += 1;
|
|
let mut socket = if let Ok(x) = connect_async(url_parsed.clone()).await {
|
|
let mut socket = if let Ok(x) = connect_async(url_parsed.clone()).await {
|
|
@@ -117,17 +125,18 @@ impl Client {
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- log::error!("{} Reconnecting client due of empty recv", url);
|
|
|
|
|
|
+ log::error!("{} Reconnecting client due of empty recv: {:?}", url, msg);
|
|
break;
|
|
break;
|
|
};
|
|
};
|
|
|
|
|
|
- log::info!("New message: {}", msg);
|
|
|
|
- retries = 0;
|
|
|
|
-
|
|
|
|
if msg.is_empty() {
|
|
if msg.is_empty() {
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ log::info!("New message: {}", msg);
|
|
|
|
+ retries = 0;
|
|
|
|
+
|
|
|
|
+
|
|
let msg: Result<Response, _> = serde_json::from_str(&msg);
|
|
let msg: Result<Response, _> = serde_json::from_str(&msg);
|
|
|
|
|
|
if let Ok(msg) = msg {
|
|
if let Ok(msg) = msg {
|
|
@@ -142,6 +151,8 @@ impl Client {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ // Throttle down to not spam the server with reconnections
|
|
|
|
+ sleep(Duration::from_millis(500)).await;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -151,10 +162,13 @@ impl Client {
|
|
Ok((recv_from_socket, stop_service))
|
|
Ok((recv_from_socket, stop_service))
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /// Checks if the relayer background connection is running
|
|
pub fn is_running(&self) -> bool {
|
|
pub fn is_running(&self) -> bool {
|
|
!self.stop_service.is_closed()
|
|
!self.stop_service.is_closed()
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /// Subscribe to responses sent through this relayer. If the relayer is not
|
|
|
|
+ /// running, this will return None
|
|
pub fn subscribe(&self) -> Option<broadcast::Receiver<(Response, String)>> {
|
|
pub fn subscribe(&self) -> Option<broadcast::Receiver<(Response, String)>> {
|
|
if self.stop_service.is_closed() {
|
|
if self.stop_service.is_closed() {
|
|
None
|
|
None
|
|
@@ -163,10 +177,12 @@ impl Client {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /// Sends a requests to this relayer
|
|
pub async fn send(&self, request: Request) -> Result<(), Error> {
|
|
pub async fn send(&self, request: Request) -> Result<(), Error> {
|
|
Ok(self.send_to_socket.send(request).await?)
|
|
Ok(self.send_to_socket.send(request).await?)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /// Stops the background thread that has the connection to this relayer
|
|
pub async fn stop(self) {
|
|
pub async fn stop(self) {
|
|
let _ = self.stop_service.send(());
|
|
let _ = self.stop_service.send(());
|
|
}
|
|
}
|