|
@@ -1,4 +1,7 @@
|
|
|
-use crate::{Client, Error};
|
|
|
+//! Relayers
|
|
|
+//!
|
|
|
+//! This is the main entry point to the client library.
|
|
|
+use crate::{Error, Relayer};
|
|
|
use futures::Future;
|
|
|
use futures_util::{stream::FuturesUnordered, StreamExt};
|
|
|
use nostr_rs_types::{Request, Response};
|
|
@@ -6,13 +9,18 @@ use parking_lot::RwLock;
|
|
|
use std::{collections::HashMap, pin::Pin, sync::Arc};
|
|
|
use tokio::sync::mpsc;
|
|
|
|
|
|
+/// Clients
|
|
|
+///
|
|
|
+/// 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
|
|
|
+/// time, and to receive messages
|
|
|
#[derive(Debug, Clone)]
|
|
|
-pub struct Clients {
|
|
|
- clients: Arc<RwLock<HashMap<String, Client>>>,
|
|
|
+pub struct Relayers {
|
|
|
+ clients: Arc<RwLock<HashMap<String, Relayer>>>,
|
|
|
messages: Arc<RwLock<Vec<Request>>>,
|
|
|
}
|
|
|
|
|
|
-impl Default for Clients {
|
|
|
+impl Default for Relayers {
|
|
|
fn default() -> Self {
|
|
|
Self {
|
|
|
clients: Arc::new(RwLock::new(HashMap::new())),
|
|
@@ -21,7 +29,8 @@ impl Default for Clients {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-impl Clients {
|
|
|
+impl 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
|
|
@@ -50,6 +59,8 @@ impl Clients {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// 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
|
|
@@ -73,6 +84,8 @@ impl Clients {
|
|
|
Ok(None)
|
|
|
}
|
|
|
|
|
|
+ /// Returns the number of active connections. If a connection to a relayer
|
|
|
+ /// is not active it will be removed from the list
|
|
|
pub fn check_active_connections(&self) -> usize {
|
|
|
let mut clients = self.clients.write();
|
|
|
let mut to_remove = vec![];
|
|
@@ -89,6 +102,7 @@ impl Clients {
|
|
|
clients.len()
|
|
|
}
|
|
|
|
|
|
+ /// Sends a request to all the connected relayers
|
|
|
pub async fn send(&self, request: Request) {
|
|
|
let senders = self
|
|
|
.clients
|
|
@@ -105,11 +119,22 @@ impl Clients {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- pub fn get_sent_messages(&self) -> Vec<Request> {
|
|
|
- self.messages.read().to_owned()
|
|
|
- }
|
|
|
-
|
|
|
- pub async fn connect_to<F>(&self, url: &str, on_connection: Option<F>) -> Result<bool, Error>
|
|
|
+ /// Creates a connection to a new relayer. If the connection is successful a
|
|
|
+ /// Callback will be called, with a list of previously sent requests, and a
|
|
|
+ /// Sender to send new requests to this relayer alone.
|
|
|
+ ///
|
|
|
+ /// The same callback will be called for every reconnection to the same
|
|
|
+ /// relayer, also the callback will be called, giving the chance to re-send
|
|
|
+ /// sent requests to the new connections
|
|
|
+ ///
|
|
|
+ /// This function will open a connection at most once, if a connection
|
|
|
+ /// already exists false will be returned
|
|
|
+ pub async fn connect_to<F>(
|
|
|
+ &self,
|
|
|
+ url: &str,
|
|
|
+ connection_retries: u16,
|
|
|
+ on_connection: Option<F>,
|
|
|
+ ) -> Result<bool, Error>
|
|
|
where
|
|
|
F: (Fn(Vec<Request>, mpsc::Sender<Request>) -> Pin<Box<dyn Future<Output = ()> + Send>>)
|
|
|
+ Send
|
|
@@ -123,9 +148,26 @@ impl Clients {
|
|
|
log::warn!("Connecting to {}", url);
|
|
|
clients.insert(
|
|
|
url.to_owned(),
|
|
|
- Client::new(self.messages.clone(), url, on_connection)?,
|
|
|
+ Relayer::new(
|
|
|
+ self.messages.clone(),
|
|
|
+ connection_retries,
|
|
|
+ url,
|
|
|
+ on_connection,
|
|
|
+ )?,
|
|
|
);
|
|
|
true
|
|
|
})
|
|
|
}
|
|
|
+
|
|
|
+ /// Disconnects from all relayers
|
|
|
+ pub async fn stop(&self) {
|
|
|
+ let mut clients = self.clients.write();
|
|
|
+ let keys = clients.keys().cloned().collect::<Vec<_>>();
|
|
|
+
|
|
|
+ for key in keys.iter() {
|
|
|
+ if let Some(client) = clients.remove(key) {
|
|
|
+ client.stop().await;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|