ソースを参照

Fixed bug with key prefix in subscription manager

The offset for key prefix was incorrect generating partial matches but not full
matches of keys.

The bug was fixed while working on another branch and tests has been added
Cesar Rodas 2 ヶ月 前
コミット
b753fee336
2 ファイル変更94 行追加22 行削除
  1. 80 0
      crates/relayer/src/relayer.rs
  2. 14 22
      crates/relayer/src/subscription/manager.rs

+ 80 - 0
crates/relayer/src/relayer.rs

@@ -475,6 +475,86 @@ mod test {
     }
     }
 
 
     #[tokio::test]
     #[tokio::test]
+    async fn server_listener_real_time_single_argument() {
+        let request: Request = serde_json::from_value(json!(
+            [
+                "REQ",
+                "1298169700973717",
+                {
+                    "authors": ["39a7d06e824c0c2523bedb93f0cef84245e4401fee03b6257a1c6dfd18b57efb"],
+                    "since":1681939304
+                },
+                {
+                    "#p":["39a7d06e824c0c2523bedb93f0cef84245e4401fee03b6257a1c6dfd18b57efb"],
+                    "since":1681939304
+                },
+                {
+                    "#p":["39a7d06e824c0c2523bedb93f0cef84245e4401fee03b6257a1c6dfd18b57efb"],
+                },
+                {
+                    "authors":["39a7d06e824c0c2523bedb93f0cef84245e4401fee03b6257a1c6dfd18b57efb"],
+                },
+                {
+                    "#e":[
+                        "2e72250d80e9b3fd30230b3db3ed7d22f15d266ed345c36700b01ec153c9e28a",
+                        "a5e3369c43daf2675ecbce18831e5f4e07db0d4dde0ef4f5698e645e4c46eed1"
+                    ],
+                }
+        ]))
+        .expect("valid object");
+        let relayer = Relayer::new(Some(get_db(false).await), None).expect("valid relayer");
+        let (connection, mut recv) = Connection::new_local_connection();
+
+        assert_eq!(relayer.total_subscribers(), 0);
+        let _ = relayer
+            .process_request_from_client(&connection, request)
+            .await;
+
+        assert_eq!(relayer.total_subscribers(), 5);
+
+        // eod
+        assert!(recv
+            .try_recv()
+            .expect("valid")
+            .as_end_of_stored_events()
+            .is_some());
+
+        // It is empty
+        assert!(recv.try_recv().is_err());
+
+        relayer
+            .process_request_from_client(&connection, get_note())
+            .await
+            .expect("process event");
+
+        sleep(Duration::from_millis(100)).await;
+
+        // It is not empty
+        let msg = recv.try_recv();
+        assert!(msg.is_ok());
+        assert_eq!(
+            msg.expect("is ok")
+                .as_event()
+                .expect("valid")
+                .subscription_id
+                .to_string(),
+            "1298169700973717".to_owned()
+        );
+
+        // it must be deliverd at most once
+        assert!(recv.try_recv().is_err());
+        assert_eq!(relayer.total_subscribers(), 5);
+
+        // when client is dropped, the subscription is removed
+        // automatically
+        drop(connection);
+
+        sleep(Duration::from_millis(10)).await;
+
+        assert_eq!(relayer.total_subscribers(), 0);
+    }
+
+    #[tokio::test]
     async fn server_listener_real_time() {
     async fn server_listener_real_time() {
         let request: Request = serde_json::from_value(json!(
         let request: Request = serde_json::from_value(json!(
             [
             [

+ 14 - 22
crates/relayer/src/subscription/manager.rs

@@ -16,7 +16,7 @@ use tokio::sync::{mpsc::Sender, RwLock};
 
 
 type SubIdx = (Key, ConnectionId, SubscriptionId);
 type SubIdx = (Key, ConnectionId, SubscriptionId);
 
 
-pub const MIN_PREFIX_MATCH_LEN: usize = 4;
+pub const MIN_PREFIX_MATCH_LEN: usize = 2;
 
 
 /// Subscription for a connection
 /// Subscription for a connection
 ///
 ///
@@ -110,41 +110,33 @@ impl SubscriptionManager {
         let author = event.author().as_ref().to_vec();
         let author = event.author().as_ref().to_vec();
         let id = event.id.as_ref().to_vec();
         let id = event.id.as_ref().to_vec();
 
 
-        let len = author.len();
-        for i in min_prefix_match_len..len - min_prefix_match_len {
-            subscriptions.push(Key::Author(author[..len - i].to_vec(), None));
-            subscriptions.push(Key::Author(author[..len - i].to_vec(), Some(event.kind())));
+        for i in min_prefix_match_len..=author.len() {
+            subscriptions.push(Key::Author(author[..i].to_vec(), None));
+            subscriptions.push(Key::Author(author[..i].to_vec(), Some(event.kind())));
         }
         }
 
 
         for t in event.tags() {
         for t in event.tags() {
             match t {
             match t {
                 nostr_rs_types::types::Tag::Event(ref_event) => {
                 nostr_rs_types::types::Tag::Event(ref_event) => {
-                    let len = ref_event.id.len();
-                    for i in min_prefix_match_len..ref_event.id.len() - min_prefix_match_len {
-                        subscriptions.push(Key::RefId(ref_event.id[..len - i].to_vec(), None));
-                        subscriptions.push(Key::RefId(
-                            ref_event.id[..len - i].to_vec(),
-                            Some(event.kind()),
-                        ));
+                    for i in min_prefix_match_len..=ref_event.id.len() {
+                        subscriptions.push(Key::RefId(ref_event.id[..i].to_vec(), None));
+                        subscriptions
+                            .push(Key::RefId(ref_event.id[..i].to_vec(), Some(event.kind())));
                     }
                     }
                 }
                 }
                 nostr_rs_types::types::Tag::PubKey(ref_pub_key) => {
                 nostr_rs_types::types::Tag::PubKey(ref_pub_key) => {
-                    let len = ref_pub_key.id.len();
-                    for i in min_prefix_match_len..len - min_prefix_match_len {
-                        subscriptions.push(Key::RefId(ref_pub_key.id[..len - i].to_vec(), None));
-                        subscriptions.push(Key::RefId(
-                            ref_pub_key.id[..len - i].to_vec(),
-                            Some(event.kind()),
-                        ));
+                    for i in min_prefix_match_len..=ref_pub_key.id.len() {
+                        subscriptions.push(Key::RefId(ref_pub_key.id[..i].to_vec(), None));
+                        subscriptions
+                            .push(Key::RefId(ref_pub_key.id[..i].to_vec(), Some(event.kind())));
                     }
                     }
                 }
                 }
                 _ => {}
                 _ => {}
             }
             }
         }
         }
 
 
-        let len = id.len();
-        for i in min_prefix_match_len..len - min_prefix_match_len {
-            subscriptions.push(Key::Id(id[..len - i].to_vec()));
+        for i in min_prefix_match_len..=id.len() {
+            subscriptions.push(Key::Id(id[..i].to_vec()));
         }
         }
 
 
         subscriptions.push(Key::Kind(event.kind()));
         subscriptions.push(Key::Kind(event.kind()));