|
@@ -0,0 +1,100 @@
|
|
|
+use crate::{connection::ConnectionId, subscription::Key};
|
|
|
+use futures::executor::block_on;
|
|
|
+use nostr_rs_types::{
|
|
|
+ relayer,
|
|
|
+ types::{Event, SubscriptionId},
|
|
|
+ Response,
|
|
|
+};
|
|
|
+use std::{collections::BTreeMap, sync::Arc};
|
|
|
+use tokio::sync::{mpsc::Sender, RwLock};
|
|
|
+
|
|
|
+type SubIdx = (Key, ConnectionId, SubscriptionId);
|
|
|
+
|
|
|
+/// Subscription for a connection
|
|
|
+///
|
|
|
+/// This object is responsible for keeping track of a subscription for a connection
|
|
|
+///
|
|
|
+/// When dropped their listener will be removed from the subscription manager automatically
|
|
|
+pub struct SubscriptionForConnection {
|
|
|
+ conn_id: ConnectionId,
|
|
|
+ name: SubscriptionId,
|
|
|
+ keys: Vec<Key>,
|
|
|
+ manager: Arc<SubscriptionManager>,
|
|
|
+}
|
|
|
+
|
|
|
+impl Drop for SubscriptionForConnection {
|
|
|
+ fn drop(&mut self) {
|
|
|
+ let keys = self
|
|
|
+ .keys
|
|
|
+ .drain(..)
|
|
|
+ .map(|key| (key, self.conn_id, self.name.clone()))
|
|
|
+ .collect::<Vec<_>>();
|
|
|
+
|
|
|
+ block_on(async {
|
|
|
+ self.manager.clone().unsubscribe(keys).await;
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/// Subscription manager
|
|
|
+///
|
|
|
+/// This object is responsible for letting clients and processes subscribe to
|
|
|
+/// events,
|
|
|
+#[derive(Default)]
|
|
|
+pub struct SubscriptionManager {
|
|
|
+ subscriptions: Arc<RwLock<BTreeMap<SubIdx, Sender<Response>>>>,
|
|
|
+}
|
|
|
+
|
|
|
+impl SubscriptionManager {
|
|
|
+ pub async fn unsubscribe(&self, keys: Vec<SubIdx>) {
|
|
|
+ let mut subscriptions = self.subscriptions.write().await;
|
|
|
+ for sub in keys {
|
|
|
+ subscriptions.remove(&sub);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fn get_keys_from_event(event: &Event) -> Vec<Key> {
|
|
|
+ let mut subscriptions = vec![Key::Kind(event.kind().into())];
|
|
|
+
|
|
|
+ let author = event.author().as_ref().to_vec();
|
|
|
+ let id = event.id.as_ref().to_vec();
|
|
|
+
|
|
|
+ for i in 4..author.len() {
|
|
|
+ subscriptions.push(Key::Author(author[..author.len() - i].to_vec()));
|
|
|
+ }
|
|
|
+ for i in 4..id.len() {
|
|
|
+ subscriptions.push(Key::Id(author[..author.len() - i].to_vec()));
|
|
|
+ }
|
|
|
+
|
|
|
+ subscriptions
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn publish(&self, event: Event) {
|
|
|
+ let subscriptions = self.subscriptions.clone();
|
|
|
+ tokio::spawn(async move {
|
|
|
+ let subscriptions = subscriptions.read().await;
|
|
|
+ let subs = Self::get_keys_from_event(&event);
|
|
|
+
|
|
|
+ let empty_sub_id = SubscriptionId::default();
|
|
|
+
|
|
|
+ for sub in subs {
|
|
|
+ for ((sub_type, _, sub_id), sender) in
|
|
|
+ subscriptions.range(&(sub.clone(), ConnectionId(0), empty_sub_id.clone())..)
|
|
|
+ {
|
|
|
+ if sub_type != &sub {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ let _ = sender
|
|
|
+ .send(Response::Event(relayer::Event {
|
|
|
+ subscription_id: sub_id.clone(),
|
|
|
+ event: event.clone(),
|
|
|
+ }))
|
|
|
+ .await;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ todo!()
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|