diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2025-11-19 11:55:32 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2025-11-19 15:43:29 +0000 |
| commit | fa065ad128882755f2a988d6203b59a2ab5e38ff (patch) | |
| tree | e8326de70a6e6ea56b5bf4250e0a00a3cda4afed /src/storage | |
| parent | 98c6fa4bfa897ff0b8f9c95ea698d4d065b5e9f3 (diff) | |
add landing page and nostr-relay-builder relay on same port
Diffstat (limited to 'src/storage')
| -rw-r--r-- | src/storage/mod.rs | 132 |
1 files changed, 0 insertions, 132 deletions
diff --git a/src/storage/mod.rs b/src/storage/mod.rs deleted file mode 100644 index eab8211..0000000 --- a/src/storage/mod.rs +++ /dev/null | |||
| @@ -1,132 +0,0 @@ | |||
| 1 | use anyhow::Result; | ||
| 2 | use nostr_sdk::Event; | ||
| 3 | use std::collections::HashMap; | ||
| 4 | use std::sync::Arc; | ||
| 5 | use tokio::sync::RwLock; | ||
| 6 | |||
| 7 | use crate::config::Config; | ||
| 8 | |||
| 9 | /// Simple in-memory storage for events | ||
| 10 | /// TODO: Persist to disk for production use | ||
| 11 | #[derive(Clone)] | ||
| 12 | pub struct Storage { | ||
| 13 | events: Arc<RwLock<HashMap<String, Event>>>, | ||
| 14 | data_path: String, | ||
| 15 | domain: String, | ||
| 16 | } | ||
| 17 | |||
| 18 | impl Storage { | ||
| 19 | pub fn new(config: &Config) -> Result<Self> { | ||
| 20 | // Create data directory if it doesn't exist | ||
| 21 | std::fs::create_dir_all(&config.relay_data_path)?; | ||
| 22 | |||
| 23 | Ok(Storage { | ||
| 24 | events: Arc::new(RwLock::new(HashMap::new())), | ||
| 25 | data_path: config.relay_data_path.clone(), | ||
| 26 | domain: config.domain.clone(), | ||
| 27 | }) | ||
| 28 | } | ||
| 29 | |||
| 30 | pub fn get_domain(&self) -> String { | ||
| 31 | self.domain.clone() | ||
| 32 | } | ||
| 33 | |||
| 34 | pub async fn store_event(&self, event: Event) -> Result<()> { | ||
| 35 | let mut events = self.events.write().await; | ||
| 36 | events.insert(event.id.to_hex(), event); | ||
| 37 | Ok(()) | ||
| 38 | } | ||
| 39 | |||
| 40 | pub async fn get_event(&self, event_id: &str) -> Option<Event> { | ||
| 41 | let events = self.events.read().await; | ||
| 42 | events.get(event_id).cloned() | ||
| 43 | } | ||
| 44 | |||
| 45 | pub async fn query_events<F>(&self, filter: F) -> Vec<Event> | ||
| 46 | where | ||
| 47 | F: Fn(&Event) -> bool, | ||
| 48 | { | ||
| 49 | let events = self.events.read().await; | ||
| 50 | events.values().filter(|e| filter(e)).cloned().collect() | ||
| 51 | } | ||
| 52 | |||
| 53 | pub async fn count_events(&self) -> usize { | ||
| 54 | let events = self.events.read().await; | ||
| 55 | events.len() | ||
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | #[cfg(test)] | ||
| 60 | mod tests { | ||
| 61 | use super::*; | ||
| 62 | use nostr_sdk::{EventBuilder, Keys, Kind}; | ||
| 63 | |||
| 64 | #[tokio::test] | ||
| 65 | async fn test_store_and_retrieve() { | ||
| 66 | let config = Config { | ||
| 67 | domain: "test".to_string(), | ||
| 68 | owner_npub: "npub1test".to_string(), | ||
| 69 | relay_name: "test".to_string(), | ||
| 70 | relay_description: "test".to_string(), | ||
| 71 | git_data_path: "./test_data/git".to_string(), | ||
| 72 | relay_data_path: "./test_data/relay".to_string(), | ||
| 73 | bind_address: "127.0.0.1:8080".to_string(), | ||
| 74 | }; | ||
| 75 | |||
| 76 | let storage = Storage::new(&config).unwrap(); | ||
| 77 | |||
| 78 | // Create a test event | ||
| 79 | let keys = Keys::generate(); | ||
| 80 | let event = EventBuilder::text_note("test content") | ||
| 81 | .sign_with_keys(&keys) | ||
| 82 | .unwrap(); | ||
| 83 | |||
| 84 | // Store it | ||
| 85 | storage.store_event(event.clone()).await.unwrap(); | ||
| 86 | |||
| 87 | // Retrieve it | ||
| 88 | let retrieved = storage.get_event(&event.id.to_hex()).await; | ||
| 89 | assert!(retrieved.is_some()); | ||
| 90 | assert_eq!(retrieved.unwrap().id, event.id); | ||
| 91 | |||
| 92 | // Count events | ||
| 93 | assert_eq!(storage.count_events().await, 1); | ||
| 94 | } | ||
| 95 | |||
| 96 | #[tokio::test] | ||
| 97 | async fn test_query_events() { | ||
| 98 | let config = Config { | ||
| 99 | domain: "test".to_string(), | ||
| 100 | owner_npub: "npub1test".to_string(), | ||
| 101 | relay_name: "test".to_string(), | ||
| 102 | relay_description: "test".to_string(), | ||
| 103 | git_data_path: "./test_data/git".to_string(), | ||
| 104 | relay_data_path: "./test_data/relay".to_string(), | ||
| 105 | bind_address: "127.0.0.1:8080".to_string(), | ||
| 106 | }; | ||
| 107 | |||
| 108 | let storage = Storage::new(&config).unwrap(); | ||
| 109 | |||
| 110 | // Create multiple events | ||
| 111 | let keys = Keys::generate(); | ||
| 112 | let event1 = EventBuilder::text_note("message 1") | ||
| 113 | .sign_with_keys(&keys) | ||
| 114 | .unwrap(); | ||
| 115 | let event2 = EventBuilder::text_note("message 2") | ||
| 116 | .sign_with_keys(&keys) | ||
| 117 | .unwrap(); | ||
| 118 | |||
| 119 | storage.store_event(event1.clone()).await.unwrap(); | ||
| 120 | storage.store_event(event2.clone()).await.unwrap(); | ||
| 121 | |||
| 122 | // Query all events | ||
| 123 | let all_events = storage.query_events(|_| true).await; | ||
| 124 | assert_eq!(all_events.len(), 2); | ||
| 125 | |||
| 126 | // Query by kind | ||
| 127 | let text_notes = storage | ||
| 128 | .query_events(|e| e.kind == Kind::TextNote) | ||
| 129 | .await; | ||
| 130 | assert_eq!(text_notes.len(), 2); | ||
| 131 | } | ||
| 132 | } | ||