upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/client.rs57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/lib/client.rs b/src/lib/client.rs
index 3f1f22e..8ae9820 100644
--- a/src/lib/client.rs
+++ b/src/lib/client.rs
@@ -840,6 +840,33 @@ impl Connect for Client {
840 let events: Vec<nostr::Event> = get_events_of(&relay, filters.clone(), pb).await?; 840 let events: Vec<nostr::Event> = get_events_of(&relay, filters.clone(), pb).await?;
841 // TODO: try reconcile 841 // TODO: try reconcile
842 842
843 // Track the best state event seen from this relay so callers can
844 // determine which relays have a stale or absent state event.
845 // We must do this before process_fetched_events because the local
846 // database only stores the canonical latest event; per-relay
847 // visibility is only available here.
848 for event in &events {
849 if event.kind.eq(&STATE_KIND) {
850 let entry = report
851 .state_per_relay
852 .entry(relay_url.clone())
853 .or_insert(None);
854 let is_newer = entry.as_ref().is_none_or(|existing: &nostr::Event| {
855 event.created_at.gt(&existing.created_at)
856 || (event.created_at.eq(&existing.created_at)
857 && event.id.gt(&existing.id))
858 });
859 if is_newer {
860 *entry = Some(event.clone());
861 }
862 }
863 }
864 // Mark relay as queried even if no state event was returned.
865 report
866 .state_per_relay
867 .entry(relay_url.clone())
868 .or_insert(None);
869
843 process_fetched_events( 870 process_fetched_events(
844 events, 871 events,
845 &request, 872 &request,
@@ -2018,6 +2045,30 @@ pub fn consolidate_fetch_reports(reports: Vec<Result<FetchReport>>) -> FetchRepo
2018 for c in relay_report.profile_updates { 2045 for c in relay_report.profile_updates {
2019 report.profile_updates.insert(c); 2046 report.profile_updates.insert(c);
2020 } 2047 }
2048 // Per-relay state events are independent: each relay entry is kept as-is.
2049 // If a relay appears in multiple per-relay reports (shouldn't happen in
2050 // practice but possible in tests), keep the newer event.
2051 for (relay_url, maybe_event) in relay_report.state_per_relay {
2052 match report.state_per_relay.entry(relay_url) {
2053 std::collections::hash_map::Entry::Vacant(e) => {
2054 e.insert(maybe_event);
2055 }
2056 std::collections::hash_map::Entry::Occupied(mut e) => {
2057 let keep = match (e.get(), &maybe_event) {
2058 (None, Some(_)) => true,
2059 (Some(existing), Some(incoming)) => {
2060 incoming.created_at.gt(&existing.created_at)
2061 || (incoming.created_at.eq(&existing.created_at)
2062 && incoming.id.gt(&existing.id))
2063 }
2064 _ => false,
2065 };
2066 if keep {
2067 e.insert(maybe_event);
2068 }
2069 }
2070 }
2071 }
2021 } 2072 }
2022 report 2073 report
2023} 2074}
@@ -2146,6 +2197,12 @@ pub struct FetchReport {
2146 statuses: HashSet<EventId>, 2197 statuses: HashSet<EventId>,
2147 contributor_profiles: HashSet<PublicKey>, 2198 contributor_profiles: HashSet<PublicKey>,
2148 profile_updates: HashSet<PublicKey>, 2199 profile_updates: HashSet<PublicKey>,
2200 /// The best (newest) state event seen on each relay during the fetch.
2201 /// `None` as a value means the relay was queried but returned no state
2202 /// event at all. Relays that were never queried are absent from the map.
2203 /// This is the only point at which per-relay state visibility is available;
2204 /// the local database only stores the canonical latest event.
2205 pub state_per_relay: HashMap<RelayUrl, Option<nostr::Event>>,
2149} 2206}
2150 2207
2151impl Display for FetchReport { 2208impl Display for FetchReport {