nostrdb-rs

nostrdb in rust!
git clone git://jb55.com/nostrdb-rs
Log | Files | Refs | Submodules | README | LICENSE

relay.rs (4975B)


      1 use crate::{bindings, NoteKey, Transaction};
      2 use tracing::error;
      3 
      4 #[derive(Debug)]
      5 pub struct NoteRelaysIter<'a> {
      6     _txn: &'a Transaction,
      7     iter: bindings::ndb_note_relay_iterator,
      8 }
      9 
     10 #[derive(Debug)]
     11 pub enum NoteRelays<'a> {
     12     Empty,
     13     Active(NoteRelaysIter<'a>),
     14 }
     15 
     16 impl<'a> NoteRelays<'a> {
     17     pub fn empty() -> Self {
     18         Self::Empty
     19     }
     20 
     21     pub fn new(txn: &'a Transaction, note_key: NoteKey) -> Self {
     22         Self::Active(NoteRelaysIter::new(txn, note_key))
     23     }
     24 }
     25 
     26 impl<'a> NoteRelaysIter<'a> {
     27     pub fn as_mut_ptr(&mut self) -> *mut bindings::ndb_note_relay_iterator {
     28         &mut self.iter
     29     }
     30 
     31     pub fn new(txn: &'a Transaction, note_key: NoteKey) -> Self {
     32         let note_key = note_key.as_u64();
     33         let mut val = Self {
     34             _txn: txn,
     35             iter: empty_iterator(),
     36         };
     37 
     38         let ok = unsafe {
     39             bindings::ndb_note_relay_iterate_start(txn.as_mut_ptr(), val.as_mut_ptr(), note_key)
     40         };
     41 
     42         if ok == 0 {
     43             // NOTE (jb55): this should never happen, no need to burden the api. let's log just in case?
     44             error!("error starting note relay iterator? {}", note_key);
     45         }
     46 
     47         val
     48     }
     49 }
     50 
     51 fn empty_iterator() -> bindings::ndb_note_relay_iterator {
     52     bindings::ndb_note_relay_iterator {
     53         txn: std::ptr::null_mut(),
     54         note_key: 0,
     55         cursor_op: 0,
     56         mdb_cur: std::ptr::null_mut(),
     57     }
     58 }
     59 
     60 impl<'a> Iterator for NoteRelays<'a> {
     61     type Item = &'a str;
     62 
     63     fn next(&mut self) -> Option<Self::Item> {
     64         let iter = match self {
     65             Self::Empty => {
     66                 return None;
     67             }
     68             Self::Active(iter) => iter,
     69         };
     70 
     71         let relay = unsafe { bindings::ndb_note_relay_iterate_next(iter.as_mut_ptr()) };
     72         if relay.is_null() {
     73             return None;
     74         }
     75 
     76         let relay = unsafe {
     77             let byte_slice = std::slice::from_raw_parts(relay as *const u8, libc::strlen(relay));
     78             std::str::from_utf8_unchecked(byte_slice)
     79         };
     80 
     81         Some(relay)
     82     }
     83 }
     84 
     85 impl Drop for NoteRelays<'_> {
     86     fn drop(&mut self) {
     87         let iter = match self {
     88             Self::Empty => {
     89                 return;
     90             }
     91             Self::Active(iter) => iter,
     92         };
     93 
     94         unsafe {
     95             bindings::ndb_note_relay_iterate_close(iter.as_mut_ptr());
     96         }
     97     }
     98 }
     99 
    100 #[cfg(test)]
    101 mod tests {
    102     use super::*;
    103     use crate::{config::Config, test_util, IngestMetadata, Ndb};
    104     use tokio::time::{self, sleep, Duration};
    105 
    106     #[test]
    107     fn process_event_relays_works() {
    108         let db = "target/testdbs/relays_work";
    109         test_util::cleanup_db(&db);
    110 
    111         {
    112             let ndb = Ndb::new(db, &Config::new()).expect("ndb");
    113             let eva = r#"["EVENT","s",{"id": "702555e52e82cc24ad517ba78c21879f6e47a7c0692b9b20df147916ae8731a3","pubkey": "32bf915904bfde2d136ba45dde32c88f4aca863783999faea2e847a8fafd2f15","created_at": 1702675561,"kind": 1,"tags": [],"content": "hello, world","sig": "2275c5f5417abfd644b7bc74f0388d70feb5d08b6f90fa18655dda5c95d013bfbc5258ea77c05b7e40e0ee51d8a2efa931dc7a0ec1db4c0a94519762c6625675"}]"#;
    114             ndb.process_event_with(eva, IngestMetadata::new().client(false).relay("a"))
    115                 .expect("process ok");
    116             let evb = r#"["EVENT","s",{"id": "702555e52e82cc24ad517ba78c21879f6e47a7c0692b9b20df147916ae8731a3","pubkey": "32bf915904bfde2d136ba45dde32c88f4aca863783999faea2e847a8fafd2f15","created_at": 1702675561,"kind": 1,"tags": [],"content": "hello, world","sig": "2275c5f5417abfd644b7bc74f0388d70feb5d08b6f90fa18655dda5c95d013bfbc5258ea77c05b7e40e0ee51d8a2efa931dc7a0ec1db4c0a94519762c6625675"}]"#;
    117             ndb.process_event_with(evb, IngestMetadata::new().client(false).relay("b"))
    118                 .expect("process ok");
    119             let evc = r#"["EVENT","s",{"id": "702555e52e82cc24ad517ba78c21879f6e47a7c0692b9b20df147916ae8731a3","pubkey": "32bf915904bfde2d136ba45dde32c88f4aca863783999faea2e847a8fafd2f15","created_at": 1702675561,"kind": 1,"tags": [],"content": "hello, world","sig": "2275c5f5417abfd644b7bc74f0388d70feb5d08b6f90fa18655dda5c95d013bfbc5258ea77c05b7e40e0ee51d8a2efa931dc7a0ec1db4c0a94519762c6625675"}]"#;
    120             ndb.process_event_with(evc, IngestMetadata::new().client(false).relay("c"))
    121                 .expect("process ok");
    122         }
    123 
    124         {
    125             let ndb = Ndb::new(db, &Config::new()).expect("ndb");
    126             let id =
    127                 hex::decode("702555e52e82cc24ad517ba78c21879f6e47a7c0692b9b20df147916ae8731a3")
    128                     .expect("hex id");
    129             let mut txn = Transaction::new(&ndb).expect("txn");
    130             let id_bytes: [u8; 32] = id.try_into().expect("id bytes");
    131             let note = ndb.get_note_by_id(&txn, &id_bytes).expect("note");
    132 
    133             let relays: Vec<&str> = note.relays(&txn).collect();
    134             assert_eq!(relays, vec!["a", "b", "c"]);
    135 
    136             assert_eq!(note.kind(), 1);
    137         }
    138     }
    139 }