|
@@ -5,7 +5,7 @@ use nostr_rs_types::{Request, Response};
|
|
use std::pin::Pin;
|
|
use std::pin::Pin;
|
|
use tokio::{
|
|
use tokio::{
|
|
sync::{broadcast, mpsc, oneshot},
|
|
sync::{broadcast, mpsc, oneshot},
|
|
- time::{sleep, Duration},
|
|
|
|
|
|
+ time::{sleep, timeout, Duration},
|
|
};
|
|
};
|
|
use tokio_tungstenite::{connect_async, tungstenite::Message};
|
|
use tokio_tungstenite::{connect_async, tungstenite::Message};
|
|
use url::Url;
|
|
use url::Url;
|
|
@@ -20,6 +20,9 @@ pub struct Client {
|
|
stop_service: oneshot::Sender<()>,
|
|
stop_service: oneshot::Sender<()>,
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+const NO_ACTIVITY_TIMEOUT_SECS: u64 = 30;
|
|
|
|
+const MAX_RECONNECT_ATTEMPTS: u64 = 15;
|
|
|
|
+
|
|
impl Client {
|
|
impl Client {
|
|
pub fn new<F>(url: &str, on_connection: Option<F>) -> Result<Self, Error>
|
|
pub fn new<F>(url: &str, on_connection: Option<F>) -> Result<Self, Error>
|
|
where
|
|
where
|
|
@@ -60,8 +63,8 @@ impl Client {
|
|
|
|
|
|
tokio::spawn(async move {
|
|
tokio::spawn(async move {
|
|
let mut reconnect = true;
|
|
let mut reconnect = true;
|
|
- let mut retries: usize = 0;
|
|
|
|
- while reconnect && retries <= 10 {
|
|
|
|
|
|
+ let mut retries = 0;
|
|
|
|
+ while reconnect && retries <= MAX_RECONNECT_ATTEMPTS {
|
|
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 {
|
|
@@ -85,29 +88,31 @@ impl Client {
|
|
reconnect = false;
|
|
reconnect = false;
|
|
break;
|
|
break;
|
|
},
|
|
},
|
|
|
|
+
|
|
Some(msg) = receiver.recv() => {
|
|
Some(msg) = receiver.recv() => {
|
|
if let Ok(json) = serde_json::to_string(&msg) {
|
|
if let Ok(json) = serde_json::to_string(&msg) {
|
|
log::info!("{}: Sending {}", url, json);
|
|
log::info!("{}: Sending {}", url, json);
|
|
if let Err(x) = socket.send(Message::Text(json)).await {
|
|
if let Err(x) = socket.send(Message::Text(json)).await {
|
|
- log::error!("{} :Reconnecting due {}", url, x);
|
|
|
|
|
|
+ log::error!("{} : Reconnecting due {}", url, x);
|
|
break;
|
|
break;
|
|
-
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- Some(Ok(msg)) = socket.next() => {
|
|
|
|
- let msg =if let Ok(msg) = msg.into_text() {
|
|
|
|
|
|
+ msg = timeout(Duration::from_secs(NO_ACTIVITY_TIMEOUT_SECS), socket.next()) => {
|
|
|
|
+ let msg =if let Ok(Some(Ok(Message::Text(msg)))) = msg {
|
|
msg
|
|
msg
|
|
} else {
|
|
} else {
|
|
- continue;
|
|
|
|
|
|
+ log::error!("{} Reconnecting client due of empty recv", url);
|
|
|
|
+ break;
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ log::info!("New message: {}", msg);
|
|
|
|
+ retries = 0;
|
|
|
|
+
|
|
if msg.is_empty() {
|
|
if msg.is_empty() {
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
- log::info!("New message: {}", msg);
|
|
|
|
-
|
|
|
|
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 {
|
|
@@ -119,6 +124,7 @@ impl Client {
|
|
}
|
|
}
|
|
else => {
|
|
else => {
|
|
log::warn!("{}: else", url);
|
|
log::warn!("{}: else", url);
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -134,8 +140,12 @@ impl Client {
|
|
!self.stop_service.is_closed()
|
|
!self.stop_service.is_closed()
|
|
}
|
|
}
|
|
|
|
|
|
- pub fn subscribe(&self) -> broadcast::Receiver<(Response, String)> {
|
|
|
|
- self.recv_from_socket.resubscribe()
|
|
|
|
|
|
+ pub fn subscribe(&self) -> Option<broadcast::Receiver<(Response, String)>> {
|
|
|
|
+ if self.stop_service.is_closed() {
|
|
|
|
+ None
|
|
|
|
+ } else {
|
|
|
|
+ Some(self.recv_from_socket.resubscribe())
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
pub async fn send(&self, request: Request) -> Result<(), Error> {
|
|
pub async fn send(&self, request: Request) -> Result<(), Error> {
|