runtime_adapter.rs (4103B)
1 use crate::ingest::RadrootsNostrNdbIngestSource; 2 use crate::ndb::RadrootsNostrNdb; 3 use radroots_nostr::prelude::RadrootsNostrEvent; 4 use radroots_nostr_runtime::prelude::RadrootsNostrEventSink; 5 use std::sync::Arc; 6 7 #[derive(Clone)] 8 pub struct RadrootsNostrNdbEventSinkAdapter { 9 ndb: RadrootsNostrNdb, 10 source: RadrootsNostrNdbIngestSource, 11 } 12 13 fn ndb_error_to_string(source: crate::error::RadrootsNostrNdbError) -> String { 14 source.to_string() 15 } 16 17 impl RadrootsNostrNdbEventSinkAdapter { 18 pub fn new(ndb: RadrootsNostrNdb) -> Self { 19 Self { 20 ndb, 21 source: RadrootsNostrNdbIngestSource::client(), 22 } 23 } 24 25 pub fn with_source(mut self, source: RadrootsNostrNdbIngestSource) -> Self { 26 self.source = source; 27 self 28 } 29 30 pub fn into_event_sink(self) -> Arc<dyn RadrootsNostrEventSink> { 31 Arc::new(self) 32 } 33 } 34 35 impl RadrootsNostrEventSink for RadrootsNostrNdb { 36 fn ingest_event(&self, event: &RadrootsNostrEvent) -> Result<(), String> { 37 RadrootsNostrNdb::ingest_event(self, event, RadrootsNostrNdbIngestSource::client()) 38 .map_err(ndb_error_to_string) 39 } 40 } 41 42 impl RadrootsNostrEventSink for RadrootsNostrNdbEventSinkAdapter { 43 fn ingest_event(&self, event: &RadrootsNostrEvent) -> Result<(), String> { 44 self.ndb 45 .ingest_event(event, self.source.clone()) 46 .map_err(ndb_error_to_string) 47 } 48 } 49 50 #[cfg(test)] 51 mod tests { 52 use super::*; 53 use crate::config::RadrootsNostrNdbConfig; 54 use radroots_nostr::prelude::{RadrootsNostrEventBuilder, RadrootsNostrKeys}; 55 use tempfile::TempDir; 56 57 #[test] 58 fn runtime_adapter_accepts_signed_events() { 59 let tmp_dir = TempDir::new().expect("tempdir should open"); 60 let db_dir = tmp_dir.path().join("ndb"); 61 let config = RadrootsNostrNdbConfig::new(&db_dir); 62 let ndb = RadrootsNostrNdb::open(config).expect("database should open"); 63 let adapter = RadrootsNostrNdbEventSinkAdapter::new(ndb); 64 65 let keys = RadrootsNostrKeys::generate(); 66 let event = RadrootsNostrEventBuilder::text_note("hello from runtime adapter") 67 .sign_with_keys(&keys) 68 .expect("event should sign"); 69 70 adapter 71 .ingest_event(&event) 72 .expect("adapter should ingest event"); 73 } 74 75 #[test] 76 fn runtime_adapter_can_be_boxed_as_sink_trait() { 77 let tmp_dir = TempDir::new().expect("tempdir should open"); 78 let db_dir = tmp_dir.path().join("ndb"); 79 let config = RadrootsNostrNdbConfig::new(&db_dir); 80 let ndb = RadrootsNostrNdb::open(config).expect("database should open"); 81 let sink = RadrootsNostrNdbEventSinkAdapter::new(ndb) 82 .with_source(RadrootsNostrNdbIngestSource::relay("wss://radroots.org")) 83 .into_event_sink(); 84 85 let keys = RadrootsNostrKeys::generate(); 86 let event = RadrootsNostrEventBuilder::text_note("hello trait object") 87 .sign_with_keys(&keys) 88 .expect("event should sign"); 89 90 sink.ingest_event(&event) 91 .expect("boxed sink should ingest event"); 92 } 93 94 #[test] 95 fn ndb_can_be_boxed_as_sink_trait() { 96 let tmp_dir = TempDir::new().expect("tempdir should open"); 97 let db_dir = tmp_dir.path().join("ndb"); 98 let config = RadrootsNostrNdbConfig::new(&db_dir); 99 let ndb = RadrootsNostrNdb::open(config).expect("database should open"); 100 let sink: Arc<dyn RadrootsNostrEventSink> = Arc::new(ndb.clone()); 101 102 let keys = RadrootsNostrKeys::generate(); 103 let event = RadrootsNostrEventBuilder::text_note("hello ndb trait object") 104 .sign_with_keys(&keys) 105 .expect("event should sign"); 106 107 sink.ingest_event(&event) 108 .expect("ndb trait object should ingest event"); 109 } 110 111 #[test] 112 fn runtime_adapter_error_to_string_converts() { 113 let rendered = ndb_error_to_string(crate::error::RadrootsNostrNdbError::Ndb( 114 "ndb error".to_string(), 115 )); 116 assert_eq!(rendered, "nostrdb error: ndb error"); 117 } 118 }