|
@@ -1,14 +1,14 @@
|
|
|
use crate::{
|
|
|
connection::{ConnectionId, LocalConnection},
|
|
|
- subscription::SubscriptionManager,
|
|
|
Connection, Error,
|
|
|
};
|
|
|
use futures_util::StreamExt;
|
|
|
use nostr_rs_client::{Error as ClientError, Pool, Url};
|
|
|
use nostr_rs_storage_base::Storage;
|
|
|
+use nostr_rs_subscription_manager::SubscriptionManager;
|
|
|
use nostr_rs_types::{
|
|
|
relayer::{self, ROk, ROkStatus},
|
|
|
- types::{Addr, Event},
|
|
|
+ types::{Addr, Event, SubscriptionId},
|
|
|
Request, Response,
|
|
|
};
|
|
|
use std::{
|
|
@@ -25,6 +25,21 @@ use tokio::{
|
|
|
task::JoinHandle,
|
|
|
};
|
|
|
|
|
|
+#[derive(Debug, Hash, Ord, PartialEq, PartialOrd, Eq, Clone)]
|
|
|
+pub struct RelayerSubscriptionId((SubscriptionId, ConnectionId));
|
|
|
+
|
|
|
+impl From<(SubscriptionId, ConnectionId)> for RelayerSubscriptionId {
|
|
|
+ fn from(value: (SubscriptionId, ConnectionId)) -> Self {
|
|
|
+ Self(value)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl Default for RelayerSubscriptionId {
|
|
|
+ fn default() -> Self {
|
|
|
+ Self((SubscriptionId::empty(), ConnectionId::new_empty()))
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/// Relayer struct
|
|
|
///
|
|
|
pub struct Relayer<T: Storage + Send + Sync + 'static> {
|
|
@@ -34,7 +49,7 @@ pub struct Relayer<T: Storage + Send + Sync + 'static> {
|
|
|
/// be able to perform any optimization like prefetching content while offline
|
|
|
storage: Option<T>,
|
|
|
/// Subscription manager
|
|
|
- subscription_manager: Arc<SubscriptionManager>,
|
|
|
+ subscription_manager: Arc<SubscriptionManager<RelayerSubscriptionId, ()>>,
|
|
|
/// List of all active connections
|
|
|
connections: RwLock<HashMap<ConnectionId, Connection>>,
|
|
|
/// This Sender can be used to send requests from anywhere to the relayer.
|
|
@@ -158,9 +173,6 @@ impl<T: Storage + Send + Sync + 'static> Relayer<T> {
|
|
|
|
|
|
let handle = tokio::spawn(async move {
|
|
|
loop {
|
|
|
- if receiver.len() > 500 {
|
|
|
- println!("{}", receiver.len());
|
|
|
- }
|
|
|
if let Some((response, _)) = receiver.recv().await {
|
|
|
match response {
|
|
|
Response::Event(event) => {
|
|
@@ -187,12 +199,33 @@ impl<T: Storage + Send + Sync + 'static> Relayer<T> {
|
|
|
}
|
|
|
|
|
|
/// Adds a new local connection to the list of active connections.
|
|
|
- pub async fn create_new_local_connection(&self) -> LocalConnection {
|
|
|
+ pub async fn create_new_local_connection(self: &Arc<Self>) -> LocalConnection<T> {
|
|
|
let (conn, receiver) = Connection::new_local_connection();
|
|
|
let conn_id = conn.get_conn_id();
|
|
|
self.connections.write().await.insert(conn_id, conn);
|
|
|
|
|
|
- (conn_id, receiver, self.send_to_relayer.clone()).into()
|
|
|
+ (
|
|
|
+ conn_id,
|
|
|
+ receiver,
|
|
|
+ self.send_to_relayer.clone(),
|
|
|
+ self.clone(),
|
|
|
+ )
|
|
|
+ .into()
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Drops a connection from the list of active connections
|
|
|
+ ///
|
|
|
+ /// This function only works for local connections, normal connections can
|
|
|
+ /// be dropped on disconnection.
|
|
|
+ ///
|
|
|
+ /// This function could change in the future tu kick connections programmatically
|
|
|
+ pub fn drop_connection(self: &Arc<Self>, local_connection: &LocalConnection<T>) {
|
|
|
+ let id = local_connection.conn_id.clone();
|
|
|
+ let this = self.clone();
|
|
|
+
|
|
|
+ tokio::spawn(async move {
|
|
|
+ this.connections.write().await.remove(&id);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
/// Adds a new TpStream and adds it to the list of active connections.
|
|
@@ -292,9 +325,9 @@ impl<T: Storage + Send + Sync + 'static> Relayer<T> {
|
|
|
foreign_subscription,
|
|
|
self.subscription_manager
|
|
|
.subscribe(
|
|
|
- connection.get_conn_id(),
|
|
|
- connection.get_sender(),
|
|
|
- request.clone(),
|
|
|
+ (request.subscription_id, connection.get_conn_id()).into(),
|
|
|
+ request.filters,
|
|
|
+ (),
|
|
|
)
|
|
|
.await,
|
|
|
),
|
|
@@ -318,7 +351,20 @@ impl<T: Storage + Send + Sync + 'static> Relayer<T> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- self.subscription_manager.broadcast(event.clone());
|
|
|
+ let connections = self.connections.read().await;
|
|
|
+ for RelayerSubscriptionId((sub_id, conn_id)) in
|
|
|
+ self.subscription_manager.get_subscribers(event).await
|
|
|
+ {
|
|
|
+ if let Some(connection) = connections.get(&conn_id) {
|
|
|
+ let _ = connection.send(
|
|
|
+ relayer::Event {
|
|
|
+ subscription_id: sub_id,
|
|
|
+ event: event.clone(),
|
|
|
+ }
|
|
|
+ .into(),
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
Ok(true)
|
|
|
}
|
|
|
}
|
|
@@ -354,6 +400,17 @@ mod test {
|
|
|
)
|
|
|
}
|
|
|
|
|
|
+ async fn dummy_server_with_relayer(
|
|
|
+ client_pool: Option<Pool>,
|
|
|
+ ) -> (Arc<Relayer<Memory>>, JoinHandle<()>) {
|
|
|
+ let listener = TcpListener::bind(format!("127.0.0.1:{}", 0)).await.unwrap();
|
|
|
+
|
|
|
+ let relayer =
|
|
|
+ Relayer::new(Some(Memory::default()), client_pool).expect("valid dummy server");
|
|
|
+ let (relayer, stopper) = relayer.main(listener).expect("valid main loop");
|
|
|
+ (relayer, stopper)
|
|
|
+ }
|
|
|
+
|
|
|
fn get_note_with_custom_tags(tags: Vec<Tag>) -> Event {
|
|
|
let account = Account::default();
|
|
|
let content = Content::ShortTextNote("".to_owned());
|
|
@@ -582,44 +639,43 @@ mod test {
|
|
|
}
|
|
|
]))
|
|
|
.expect("valid object");
|
|
|
- let relayer = Relayer::new(Some(get_db(false).await), None).expect("valid relayer");
|
|
|
- let (connection, mut recv) = Connection::new_local_connection();
|
|
|
+ let (relayer, _stopper) = dummy_server_with_relayer(None).await;
|
|
|
+ let mut receiver = relayer.create_new_local_connection().await;
|
|
|
+ let mut publisher = relayer.create_new_local_connection().await;
|
|
|
|
|
|
assert_eq!(relayer.total_subscribers(), 0);
|
|
|
- let _ = relayer
|
|
|
- .process_request_from_client(&connection, request)
|
|
|
- .await;
|
|
|
|
|
|
- assert_eq!(relayer.total_subscribers(), 5);
|
|
|
+ receiver.send(request).await.expect("subscribe");
|
|
|
+
|
|
|
+ sleep(Duration::from_millis(10)).await;
|
|
|
+
|
|
|
+ assert_eq!(relayer.total_subscribers(), 1);
|
|
|
|
|
|
// eod
|
|
|
- assert!(recv
|
|
|
+ assert!(receiver
|
|
|
.try_recv()
|
|
|
.expect("valid")
|
|
|
.as_end_of_stored_events()
|
|
|
.is_some());
|
|
|
|
|
|
// It is empty
|
|
|
- assert!(recv.try_recv().is_err());
|
|
|
+ assert!(receiver.try_recv().is_none());
|
|
|
|
|
|
- relayer
|
|
|
- .process_request_from_client(&connection, get_note())
|
|
|
- .await
|
|
|
- .expect("process event");
|
|
|
+ publisher.send(get_note()).await.expect("valid send");
|
|
|
|
|
|
- sleep(Duration::from_millis(100)).await;
|
|
|
+ sleep(Duration::from_millis(10)).await;
|
|
|
|
|
|
// ok from posting
|
|
|
- let msg = recv.try_recv();
|
|
|
- assert!(msg.is_ok());
|
|
|
+ let msg = publisher.try_recv();
|
|
|
+ assert!(msg.is_some());
|
|
|
assert_eq!(
|
|
|
msg.expect("is ok").as_ok().expect("valid").id.to_hex(),
|
|
|
"e862fe23daf52ab09b36a37fa91ca3743e0c323e630e8627891212ca147c2da9".to_owned(),
|
|
|
);
|
|
|
|
|
|
// It is not empty
|
|
|
- let msg = recv.try_recv();
|
|
|
- assert!(msg.is_ok());
|
|
|
+ let msg = receiver.try_recv();
|
|
|
+ assert!(msg.is_some());
|
|
|
assert_eq!(
|
|
|
msg.expect("is ok")
|
|
|
.as_event()
|
|
@@ -630,12 +686,12 @@ mod test {
|
|
|
);
|
|
|
|
|
|
// it must be deliverd at most once
|
|
|
- assert!(recv.try_recv().is_err());
|
|
|
- assert_eq!(relayer.total_subscribers(), 5);
|
|
|
+ assert!(receiver.try_recv().is_none());
|
|
|
+ assert_eq!(relayer.total_subscribers(), 1);
|
|
|
|
|
|
// when client is dropped, the subscription is removed
|
|
|
// automatically
|
|
|
- drop(connection);
|
|
|
+ drop(receiver);
|
|
|
|
|
|
sleep(Duration::from_millis(10)).await;
|
|
|
|
|
@@ -674,44 +730,44 @@ mod test {
|
|
|
}
|
|
|
]))
|
|
|
.expect("valid object");
|
|
|
- let relayer = Relayer::new(Some(get_db(false).await), None).expect("valid relayer");
|
|
|
- let (connection, mut recv) = Connection::new_local_connection();
|
|
|
+
|
|
|
+ let (relayer, _stopper) = dummy_server_with_relayer(None).await;
|
|
|
+
|
|
|
+ let mut receiver = relayer.create_new_local_connection().await;
|
|
|
+ let mut publisher = relayer.create_new_local_connection().await;
|
|
|
|
|
|
assert_eq!(relayer.total_subscribers(), 0);
|
|
|
- let _ = relayer
|
|
|
- .process_request_from_client(&connection, request)
|
|
|
- .await;
|
|
|
|
|
|
- assert_eq!(relayer.total_subscribers(), 5);
|
|
|
+ receiver.send(request).await.expect("subscribe");
|
|
|
+ sleep(Duration::from_millis(10)).await;
|
|
|
+
|
|
|
+ assert_eq!(relayer.total_subscribers(), 1);
|
|
|
|
|
|
// eod
|
|
|
- assert!(recv
|
|
|
+ assert!(receiver
|
|
|
.try_recv()
|
|
|
.expect("valid")
|
|
|
.as_end_of_stored_events()
|
|
|
.is_some());
|
|
|
|
|
|
// It is empty
|
|
|
- assert!(recv.try_recv().is_err());
|
|
|
+ assert!(receiver.try_recv().is_none());
|
|
|
|
|
|
- relayer
|
|
|
- .process_request_from_client(&connection, get_note())
|
|
|
- .await
|
|
|
- .expect("process event");
|
|
|
+ publisher.send(get_note()).await.expect("valid send");
|
|
|
|
|
|
sleep(Duration::from_millis(100)).await;
|
|
|
|
|
|
// ok from posting
|
|
|
- let msg = recv.try_recv();
|
|
|
- assert!(msg.is_ok());
|
|
|
+ let msg = publisher.try_recv();
|
|
|
+ assert!(msg.is_some());
|
|
|
assert_eq!(
|
|
|
msg.expect("is ok").as_ok().expect("valid").id.to_hex(),
|
|
|
"e862fe23daf52ab09b36a37fa91ca3743e0c323e630e8627891212ca147c2da9".to_owned(),
|
|
|
);
|
|
|
|
|
|
// It is not empty
|
|
|
- let msg = recv.try_recv();
|
|
|
- assert!(msg.is_ok());
|
|
|
+ let msg = receiver.try_recv();
|
|
|
+ assert!(msg.is_some());
|
|
|
assert_eq!(
|
|
|
msg.expect("is ok")
|
|
|
.as_event()
|
|
@@ -722,12 +778,12 @@ mod test {
|
|
|
);
|
|
|
|
|
|
// it must be deliverd at most once
|
|
|
- assert!(recv.try_recv().is_err());
|
|
|
- assert_eq!(relayer.total_subscribers(), 5);
|
|
|
+ assert!(receiver.try_recv().is_none());
|
|
|
+ assert_eq!(relayer.total_subscribers(), 1);
|
|
|
|
|
|
// when client is dropped, the subscription is removed
|
|
|
// automatically
|
|
|
- drop(connection);
|
|
|
+ drop(receiver);
|
|
|
|
|
|
sleep(Duration::from_millis(10)).await;
|
|
|
|
|
@@ -745,50 +801,57 @@ mod test {
|
|
|
}]))
|
|
|
.expect("valid object");
|
|
|
|
|
|
- let relayer = Relayer::new(Some(get_db(false).await), None).expect("valid relayer");
|
|
|
- let (publisher, mut recv) = Connection::new_local_connection();
|
|
|
+ let (relayer, _stopper) = dummy_server_with_relayer(None).await;
|
|
|
+ let mut publisher = relayer.create_new_local_connection().await;
|
|
|
|
|
|
- let mut set1 = (0..1000)
|
|
|
- .map(|_| Connection::new_local_connection())
|
|
|
- .collect::<Vec<_>>();
|
|
|
-
|
|
|
- let mut set2 = (0..100)
|
|
|
- .map(|_| Connection::new_local_connection())
|
|
|
- .collect::<Vec<_>>();
|
|
|
-
|
|
|
- let subscribe1 = set1
|
|
|
- .iter()
|
|
|
- .map(|(connection, _)| relayer.process_request_from_client(connection, req1.clone()))
|
|
|
- .collect::<Vec<_>>();
|
|
|
+ let mut set1 = join_all(
|
|
|
+ (0..1000)
|
|
|
+ .map(|_| relayer.create_new_local_connection())
|
|
|
+ .collect::<Vec<_>>(),
|
|
|
+ )
|
|
|
+ .await;
|
|
|
|
|
|
- let subscribe2 = set2
|
|
|
- .iter()
|
|
|
- .map(|(connection, _)| relayer.process_request_from_client(connection, req2.clone()))
|
|
|
- .collect::<Vec<_>>();
|
|
|
+ let mut set2 = join_all(
|
|
|
+ (0..100)
|
|
|
+ .map(|_| relayer.create_new_local_connection())
|
|
|
+ .collect::<Vec<_>>(),
|
|
|
+ )
|
|
|
+ .await;
|
|
|
|
|
|
assert_eq!(relayer.total_subscribers(), 0);
|
|
|
|
|
|
- join_all(subscribe1)
|
|
|
- .await
|
|
|
- .into_iter()
|
|
|
- .collect::<Result<Vec<_>, _>>()
|
|
|
- .expect("valid calls");
|
|
|
- join_all(subscribe2)
|
|
|
- .await
|
|
|
- .into_iter()
|
|
|
- .collect::<Result<Vec<_>, _>>()
|
|
|
- .expect("valid calls");
|
|
|
+ join_all(
|
|
|
+ set1.iter()
|
|
|
+ .map(|connection| connection.send(req1.clone()))
|
|
|
+ .collect::<Vec<_>>(),
|
|
|
+ )
|
|
|
+ .await
|
|
|
+ .into_iter()
|
|
|
+ .collect::<Result<Vec<_>, _>>()
|
|
|
+ .expect("subscribe all");
|
|
|
+
|
|
|
+ join_all(
|
|
|
+ set2.iter()
|
|
|
+ .map(|connection| connection.send(req2.clone()))
|
|
|
+ .collect::<Vec<_>>(),
|
|
|
+ )
|
|
|
+ .await
|
|
|
+ .into_iter()
|
|
|
+ .collect::<Result<Vec<_>, _>>()
|
|
|
+ .expect("subscribe all");
|
|
|
|
|
|
- for (_, recv) in set1.iter_mut() {
|
|
|
- assert!(recv
|
|
|
+ sleep(Duration::from_millis(10)).await;
|
|
|
+
|
|
|
+ for connection in set1.iter_mut() {
|
|
|
+ assert!(connection
|
|
|
.try_recv()
|
|
|
.expect("end of stored events")
|
|
|
.as_end_of_stored_events()
|
|
|
.is_some());
|
|
|
}
|
|
|
|
|
|
- for (_, recv) in set2.iter_mut() {
|
|
|
- assert!(recv
|
|
|
+ for connection in set2.iter_mut() {
|
|
|
+ assert!(connection
|
|
|
.try_recv()
|
|
|
.expect("end of stored events")
|
|
|
.as_end_of_stored_events()
|
|
@@ -797,28 +860,24 @@ mod test {
|
|
|
|
|
|
assert_eq!(relayer.total_subscribers(), 1100);
|
|
|
|
|
|
- relayer
|
|
|
- .process_request_from_client(&publisher, get_note())
|
|
|
- .await
|
|
|
- .expect("process event");
|
|
|
+ publisher.send(get_note().into()).await.expect("valid send");
|
|
|
|
|
|
sleep(Duration::from_millis(10)).await;
|
|
|
|
|
|
- let msg = recv.try_recv();
|
|
|
- assert!(msg.is_ok());
|
|
|
+ let msg = publisher.try_recv();
|
|
|
+ assert!(msg.is_some());
|
|
|
assert_eq!(
|
|
|
msg.expect("is ok").as_ok().expect("valid").id.to_hex(),
|
|
|
"e862fe23daf52ab09b36a37fa91ca3743e0c323e630e8627891212ca147c2da9".to_owned(),
|
|
|
);
|
|
|
|
|
|
- for (_, recv) in set1.iter_mut() {
|
|
|
- assert!(recv.try_recv().is_err());
|
|
|
+ for connection in set1.iter_mut() {
|
|
|
+ assert!(connection.try_recv().is_none());
|
|
|
}
|
|
|
|
|
|
- for (_, recv) in set2.iter_mut() {
|
|
|
- let msg = recv.try_recv();
|
|
|
- println!("{:?}", msg);
|
|
|
- assert!(msg.is_ok());
|
|
|
+ for connection in set2.iter_mut() {
|
|
|
+ let msg = connection.try_recv();
|
|
|
+ assert!(msg.is_some());
|
|
|
let msg = msg.expect("msg");
|
|
|
|
|
|
assert_eq!(
|
|
@@ -826,7 +885,7 @@ mod test {
|
|
|
"1298169700973717".to_owned()
|
|
|
);
|
|
|
|
|
|
- assert!(recv.try_recv().is_err());
|
|
|
+ assert!(connection.try_recv().is_none());
|
|
|
}
|
|
|
|
|
|
drop(set1);
|
|
@@ -872,44 +931,47 @@ mod test {
|
|
|
let request: Request =
|
|
|
serde_json::from_value(json!(["REQ", "1298169700973717", {}])).expect("valid object");
|
|
|
|
|
|
- let relayer = Relayer::new(Some(get_db(false).await), None).expect("valid relayer");
|
|
|
- let (connection, mut recv) = Connection::new_local_connection();
|
|
|
+ let (relayer, _stopper) = dummy_server_with_relayer(None).await;
|
|
|
+
|
|
|
+ let mut local_connection_0 = relayer.create_new_local_connection().await;
|
|
|
+ let mut local_connection_1 = relayer.create_new_local_connection().await;
|
|
|
|
|
|
assert_eq!(relayer.total_subscribers(), 0);
|
|
|
- let _ = relayer
|
|
|
- .process_request_from_client(&connection, request)
|
|
|
- .await;
|
|
|
+
|
|
|
+ local_connection_1.send(request).await.expect("valid send");
|
|
|
+
|
|
|
+ sleep(Duration::from_millis(10)).await;
|
|
|
|
|
|
assert_eq!(relayer.total_subscribers(), 1);
|
|
|
|
|
|
// eod
|
|
|
- assert!(recv
|
|
|
+ assert!(local_connection_1
|
|
|
.try_recv()
|
|
|
.expect("valid")
|
|
|
.as_end_of_stored_events()
|
|
|
.is_some());
|
|
|
|
|
|
// It is empty
|
|
|
- assert!(recv.try_recv().is_err());
|
|
|
+ assert!(local_connection_1.try_recv().is_none());
|
|
|
|
|
|
- relayer
|
|
|
- .process_request_from_client(&connection, get_note())
|
|
|
+ local_connection_0
|
|
|
+ .send(get_note().into())
|
|
|
.await
|
|
|
- .expect("process event");
|
|
|
+ .expect("valid send");
|
|
|
|
|
|
sleep(Duration::from_millis(10)).await;
|
|
|
|
|
|
// ok from posting
|
|
|
- let msg = recv.try_recv();
|
|
|
- assert!(msg.is_ok());
|
|
|
+ let msg = local_connection_0.try_recv();
|
|
|
+ assert!(msg.is_some());
|
|
|
assert_eq!(
|
|
|
msg.expect("is ok").as_ok().expect("valid").id.to_hex(),
|
|
|
"e862fe23daf52ab09b36a37fa91ca3743e0c323e630e8627891212ca147c2da9".to_owned(),
|
|
|
);
|
|
|
|
|
|
// It is not empty
|
|
|
- let msg = recv.try_recv();
|
|
|
- assert!(msg.is_ok());
|
|
|
+ let msg = local_connection_1.try_recv();
|
|
|
+ assert!(msg.is_some());
|
|
|
assert_eq!(
|
|
|
msg.expect("is ok")
|
|
|
.as_event()
|
|
@@ -920,12 +982,12 @@ mod test {
|
|
|
);
|
|
|
|
|
|
// it must be deliverd at most once
|
|
|
- assert!(recv.try_recv().is_err());
|
|
|
+ assert!(local_connection_1.try_recv().is_none());
|
|
|
assert_eq!(relayer.total_subscribers(), 1);
|
|
|
|
|
|
// when client is dropped, the subscription is removed
|
|
|
// automatically
|
|
|
- drop(connection);
|
|
|
+ drop(local_connection_1);
|
|
|
|
|
|
sleep(Duration::from_millis(10)).await;
|
|
|
|