status.rs (2546B)
1 use radroots_nostr::prelude::{RadrootsNostrMonitorNotification, RadrootsNostrRelayStatus}; 2 use tracing::{info, warn}; 3 4 use super::manager::NostrClientManager; 5 use super::types::{Light, NostrConnectionSnapshot}; 6 7 impl NostrClientManager { 8 pub(super) fn spawn_status_watcher(&self) { 9 let inner = self.inner.clone(); 10 let rt = inner.rt.clone(); 11 let inner_for_task = inner.clone(); 12 13 rt.spawn(async move { 14 if let Some(monitor) = inner_for_task.client.monitor() { 15 let mut rx = monitor.subscribe(); 16 while let Ok(notification) = rx.recv().await { 17 match notification { 18 RadrootsNostrMonitorNotification::StatusChanged { relay_url, status } => { 19 if let Ok(mut map) = inner_for_task.statuses.lock() { 20 map.insert(relay_url.clone(), status); 21 } else if let Ok(mut last) = inner_for_task.last_error.lock() { 22 *last = Some("status watcher: statuses mutex poisoned".to_string()); 23 warn!( 24 "status watcher: statuses mutex poisoned; dropping update for {}", 25 relay_url 26 ); 27 continue; 28 } 29 30 info!("relay status changed {} -> {:?}", relay_url, status); 31 } 32 } 33 } 34 } 35 }); 36 } 37 38 pub fn snapshot(&self) -> NostrConnectionSnapshot { 39 let map = self 40 .inner 41 .statuses 42 .lock() 43 .ok() 44 .map(|g| g.clone()) 45 .unwrap_or_default(); 46 47 let mut connected = 0usize; 48 let mut connecting = 0usize; 49 50 for (_url, st) in map.iter() { 51 match st { 52 RadrootsNostrRelayStatus::Connected => connected += 1, 53 RadrootsNostrRelayStatus::Connecting => connecting += 1, 54 _ => {} 55 } 56 } 57 58 let light = if connected > 0 { 59 Light::Green 60 } else if connecting > 0 { 61 Light::Yellow 62 } else { 63 Light::Red 64 }; 65 66 let last_error = self.inner.last_error.lock().ok().and_then(|e| e.clone()); 67 68 NostrConnectionSnapshot { 69 light, 70 connected, 71 connecting, 72 last_error, 73 } 74 } 75 }