|
@@ -3,7 +3,6 @@
|
|
//! This is the main entry point to the client library.
|
|
//! This is the main entry point to the client library.
|
|
use crate::{Error, Relayer};
|
|
use crate::{Error, Relayer};
|
|
use futures::Future;
|
|
use futures::Future;
|
|
-use futures_util::{stream::FuturesUnordered, StreamExt};
|
|
|
|
use nostr_rs_types::{Request, Response};
|
|
use nostr_rs_types::{Request, Response};
|
|
use parking_lot::RwLock;
|
|
use parking_lot::RwLock;
|
|
use std::{collections::HashMap, pin::Pin, sync::Arc};
|
|
use std::{collections::HashMap, pin::Pin, sync::Arc};
|
|
@@ -14,107 +13,55 @@ use tokio::sync::mpsc;
|
|
/// This is a set of outgoing connections to relayers. This struct can connect
|
|
/// This is a set of outgoing connections to relayers. This struct can connect
|
|
/// async to N relayers offering a simple API to talk to all of them at the same
|
|
/// async to N relayers offering a simple API to talk to all of them at the same
|
|
/// time, and to receive messages
|
|
/// time, and to receive messages
|
|
-#[derive(Debug, Clone)]
|
|
|
|
|
|
+#[derive(Debug)]
|
|
pub struct Relayers {
|
|
pub struct Relayers {
|
|
- clients: Arc<RwLock<HashMap<String, Relayer>>>,
|
|
|
|
|
|
+ clients: HashMap<String, Relayer>,
|
|
messages: Arc<RwLock<Vec<Request>>>,
|
|
messages: Arc<RwLock<Vec<Request>>>,
|
|
|
|
+ receiver: mpsc::Receiver<(Response, String)>,
|
|
|
|
+ sender: mpsc::Sender<(Response, String)>,
|
|
}
|
|
}
|
|
|
|
|
|
impl Default for Relayers {
|
|
impl Default for Relayers {
|
|
fn default() -> Self {
|
|
fn default() -> Self {
|
|
|
|
+ let (sender, receiver) = mpsc::channel(100_000);
|
|
Self {
|
|
Self {
|
|
- clients: Arc::new(RwLock::new(HashMap::new())),
|
|
|
|
|
|
+ clients: HashMap::new(),
|
|
messages: Arc::new(RwLock::new(vec![])),
|
|
messages: Arc::new(RwLock::new(vec![])),
|
|
|
|
+ sender,
|
|
|
|
+ receiver,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
impl Relayers {
|
|
impl Relayers {
|
|
/// Receives a Response from any of the connected relayers
|
|
/// Receives a Response from any of the connected relayers
|
|
- pub async fn recv(&self) -> Result<Option<(Response, String)>, Error> {
|
|
|
|
- let mut subscriptions = self
|
|
|
|
- .clients
|
|
|
|
- .read()
|
|
|
|
- .iter()
|
|
|
|
- .map(|(_, c)| c.subscribe())
|
|
|
|
- .collect::<Vec<Option<_>>>()
|
|
|
|
- .into_iter()
|
|
|
|
- .filter_map(|x| x)
|
|
|
|
- .collect::<Vec<_>>();
|
|
|
|
-
|
|
|
|
- if subscriptions.is_empty() {
|
|
|
|
- return Err(Error::Disconnected);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- let mut futures = FuturesUnordered::new();
|
|
|
|
-
|
|
|
|
- for sub in subscriptions.iter_mut() {
|
|
|
|
- futures.push(sub.recv());
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if let Some(Ok(response)) = futures.next().await {
|
|
|
|
- Ok(Some(response))
|
|
|
|
- } else {
|
|
|
|
- Ok(None)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /// Attempts to receive a Response from any of the relayers but won't wait if none
|
|
|
|
- /// is available. It will return None if None is available
|
|
|
|
- pub fn try_recv(&self) -> Result<Option<(Response, String)>, Error> {
|
|
|
|
- let mut subscriptions = self
|
|
|
|
- .clients
|
|
|
|
- .read()
|
|
|
|
- .iter()
|
|
|
|
- .map(|(_, c)| c.subscribe())
|
|
|
|
- .collect::<Vec<Option<_>>>()
|
|
|
|
- .into_iter()
|
|
|
|
- .filter_map(|x| x)
|
|
|
|
- .collect::<Vec<_>>();
|
|
|
|
-
|
|
|
|
- if subscriptions.is_empty() {
|
|
|
|
- return Err(Error::Disconnected);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- for sub in subscriptions.iter_mut() {
|
|
|
|
- if let Ok(msg) = sub.try_recv() {
|
|
|
|
- return Ok(Some(msg));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- Ok(None)
|
|
|
|
|
|
+ pub async fn recv(&mut self) -> Result<Option<(Response, String)>, Error> {
|
|
|
|
+ Ok(self.receiver.recv().await)
|
|
}
|
|
}
|
|
|
|
|
|
/// Returns the number of active connections. If a connection to a relayer
|
|
/// Returns the number of active connections. If a connection to a relayer
|
|
/// is not active it will be removed from the list
|
|
/// is not active it will be removed from the list
|
|
- pub fn check_active_connections(&self) -> usize {
|
|
|
|
- let mut clients = self.clients.write();
|
|
|
|
|
|
+ pub fn check_active_connections(&mut self) -> usize {
|
|
let mut to_remove = vec![];
|
|
let mut to_remove = vec![];
|
|
- for (url, client) in clients.iter() {
|
|
|
|
|
|
+ for (url, client) in self.clients.iter() {
|
|
if !client.is_running() {
|
|
if !client.is_running() {
|
|
to_remove.push(url.to_owned());
|
|
to_remove.push(url.to_owned());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
for url in to_remove.iter() {
|
|
for url in to_remove.iter() {
|
|
- clients.remove(url);
|
|
|
|
|
|
+ self.clients.remove(url);
|
|
}
|
|
}
|
|
|
|
|
|
- clients.len()
|
|
|
|
|
|
+ self.clients.len()
|
|
}
|
|
}
|
|
|
|
|
|
/// Sends a request to all the connected relayers
|
|
/// Sends a request to all the connected relayers
|
|
pub async fn send(&self, request: Request) {
|
|
pub async fn send(&self, request: Request) {
|
|
- let senders = self
|
|
|
|
- .clients
|
|
|
|
- .read()
|
|
|
|
- .iter()
|
|
|
|
- .map(|(_, c)| c.send_to_socket.clone())
|
|
|
|
- .collect::<Vec<mpsc::Sender<_>>>();
|
|
|
|
-
|
|
|
|
// Add a copy of the request for incoming connections.
|
|
// Add a copy of the request for incoming connections.
|
|
self.messages.write().push(request.clone());
|
|
self.messages.write().push(request.clone());
|
|
|
|
|
|
- for sender in senders.iter() {
|
|
|
|
|
|
+ for (_, sender) in self.clients.iter() {
|
|
let _ = sender.send(request.clone()).await;
|
|
let _ = sender.send(request.clone()).await;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -130,7 +77,7 @@ impl Relayers {
|
|
/// This function will open a connection at most once, if a connection
|
|
/// This function will open a connection at most once, if a connection
|
|
/// already exists false will be returned
|
|
/// already exists false will be returned
|
|
pub async fn connect_to<F>(
|
|
pub async fn connect_to<F>(
|
|
- &self,
|
|
|
|
|
|
+ &mut self,
|
|
url: &str,
|
|
url: &str,
|
|
connection_retries: u16,
|
|
connection_retries: u16,
|
|
on_connection: Option<F>,
|
|
on_connection: Option<F>,
|
|
@@ -141,14 +88,14 @@ impl Relayers {
|
|
+ Sync
|
|
+ Sync
|
|
+ 'static,
|
|
+ 'static,
|
|
{
|
|
{
|
|
- let mut clients = self.clients.write();
|
|
|
|
- Ok(if clients.get(url).is_some() {
|
|
|
|
|
|
+ Ok(if self.clients.get(url).is_some() {
|
|
false
|
|
false
|
|
} else {
|
|
} else {
|
|
log::warn!("Connecting to {}", url);
|
|
log::warn!("Connecting to {}", url);
|
|
- clients.insert(
|
|
|
|
|
|
+ self.clients.insert(
|
|
url.to_owned(),
|
|
url.to_owned(),
|
|
Relayer::new(
|
|
Relayer::new(
|
|
|
|
+ self.sender.clone(),
|
|
self.messages.clone(),
|
|
self.messages.clone(),
|
|
connection_retries,
|
|
connection_retries,
|
|
url,
|
|
url,
|
|
@@ -160,12 +107,11 @@ impl Relayers {
|
|
}
|
|
}
|
|
|
|
|
|
/// Disconnects from all relayers
|
|
/// Disconnects from all relayers
|
|
- pub async fn stop(&self) {
|
|
|
|
- let mut clients = self.clients.write();
|
|
|
|
- let keys = clients.keys().cloned().collect::<Vec<_>>();
|
|
|
|
|
|
+ pub async fn stop(&mut self) {
|
|
|
|
+ let keys = self.clients.keys().cloned().collect::<Vec<_>>();
|
|
|
|
|
|
for key in keys.iter() {
|
|
for key in keys.iter() {
|
|
- if let Some(client) = clients.remove(key) {
|
|
|
|
|
|
+ if let Some(client) = self.clients.remove(key) {
|
|
client.stop().await;
|
|
client.stop().await;
|
|
}
|
|
}
|
|
}
|
|
}
|