chore: refactor event fetching (#148)

* use stream for nip65 and nip17 relays fetching

* .
This commit is contained in:
reya
2025-09-13 07:42:17 +07:00
committed by GitHub
parent 2ea2519e8b
commit b142982ab1
2 changed files with 112 additions and 126 deletions

50
Cargo.lock generated
View File

@@ -894,9 +894,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.36" version = "1.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54" checksum = "65193589c6404eb80b450d618eaf9a2cafaaafd57ecce47370519ef674a7bd44"
dependencies = [ dependencies = [
"find-msvc-tools", "find-msvc-tools",
"jobserver", "jobserver",
@@ -1113,7 +1113,7 @@ dependencies = [
[[package]] [[package]]
name = "collections" name = "collections"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#9c548a0ec6d8b84e2b3b1ee2a78add5fae7a8ba7" source = "git+https://github.com/zed-industries/zed#592b013013e74d5ad44f2c04ef5afeb3be21249e"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"rustc-hash 2.1.1", "rustc-hash 2.1.1",
@@ -1554,7 +1554,7 @@ dependencies = [
[[package]] [[package]]
name = "derive_refineable" name = "derive_refineable"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#9c548a0ec6d8b84e2b3b1ee2a78add5fae7a8ba7" source = "git+https://github.com/zed-industries/zed#592b013013e74d5ad44f2c04ef5afeb3be21249e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -2480,7 +2480,7 @@ dependencies = [
[[package]] [[package]]
name = "gpui" name = "gpui"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#9c548a0ec6d8b84e2b3b1ee2a78add5fae7a8ba7" source = "git+https://github.com/zed-industries/zed#592b013013e74d5ad44f2c04ef5afeb3be21249e"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"as-raw-xcb-connection", "as-raw-xcb-connection",
@@ -2574,7 +2574,7 @@ dependencies = [
[[package]] [[package]]
name = "gpui_macros" name = "gpui_macros"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#9c548a0ec6d8b84e2b3b1ee2a78add5fae7a8ba7" source = "git+https://github.com/zed-industries/zed#592b013013e74d5ad44f2c04ef5afeb3be21249e"
dependencies = [ dependencies = [
"heck 0.5.0", "heck 0.5.0",
"proc-macro2", "proc-macro2",
@@ -2586,7 +2586,7 @@ dependencies = [
[[package]] [[package]]
name = "gpui_tokio" name = "gpui_tokio"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#9c548a0ec6d8b84e2b3b1ee2a78add5fae7a8ba7" source = "git+https://github.com/zed-industries/zed#592b013013e74d5ad44f2c04ef5afeb3be21249e"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"gpui", "gpui",
@@ -2800,7 +2800,7 @@ dependencies = [
[[package]] [[package]]
name = "http_client" name = "http_client"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#9c548a0ec6d8b84e2b3b1ee2a78add5fae7a8ba7" source = "git+https://github.com/zed-industries/zed#592b013013e74d5ad44f2c04ef5afeb3be21249e"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@@ -2820,7 +2820,7 @@ dependencies = [
[[package]] [[package]]
name = "http_client_tls" name = "http_client_tls"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#9c548a0ec6d8b84e2b3b1ee2a78add5fae7a8ba7" source = "git+https://github.com/zed-industries/zed#592b013013e74d5ad44f2c04ef5afeb3be21249e"
dependencies = [ dependencies = [
"rustls", "rustls",
"rustls-platform-verifier", "rustls-platform-verifier",
@@ -3611,7 +3611,7 @@ dependencies = [
[[package]] [[package]]
name = "media" name = "media"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#9c548a0ec6d8b84e2b3b1ee2a78add5fae7a8ba7" source = "git+https://github.com/zed-industries/zed#592b013013e74d5ad44f2c04ef5afeb3be21249e"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bindgen 0.71.1", "bindgen 0.71.1",
@@ -3859,7 +3859,7 @@ dependencies = [
[[package]] [[package]]
name = "nostr" name = "nostr"
version = "0.43.0" version = "0.43.0"
source = "git+https://github.com/rust-nostr/nostr#04ca01082044dd4192fee995b9ba101c78af3a02" source = "git+https://github.com/rust-nostr/nostr#b1016f439ef1da5f8fdeae14368f5b7340414389"
dependencies = [ dependencies = [
"aes", "aes",
"base64", "base64",
@@ -3883,7 +3883,7 @@ dependencies = [
[[package]] [[package]]
name = "nostr-connect" name = "nostr-connect"
version = "0.43.0" version = "0.43.0"
source = "git+https://github.com/rust-nostr/nostr#04ca01082044dd4192fee995b9ba101c78af3a02" source = "git+https://github.com/rust-nostr/nostr#b1016f439ef1da5f8fdeae14368f5b7340414389"
dependencies = [ dependencies = [
"async-utility", "async-utility",
"nostr", "nostr",
@@ -3895,7 +3895,7 @@ dependencies = [
[[package]] [[package]]
name = "nostr-database" name = "nostr-database"
version = "0.43.0" version = "0.43.0"
source = "git+https://github.com/rust-nostr/nostr#04ca01082044dd4192fee995b9ba101c78af3a02" source = "git+https://github.com/rust-nostr/nostr#b1016f439ef1da5f8fdeae14368f5b7340414389"
dependencies = [ dependencies = [
"flatbuffers", "flatbuffers",
"lru", "lru",
@@ -3906,7 +3906,7 @@ dependencies = [
[[package]] [[package]]
name = "nostr-lmdb" name = "nostr-lmdb"
version = "0.43.0" version = "0.43.0"
source = "git+https://github.com/rust-nostr/nostr#04ca01082044dd4192fee995b9ba101c78af3a02" source = "git+https://github.com/rust-nostr/nostr#b1016f439ef1da5f8fdeae14368f5b7340414389"
dependencies = [ dependencies = [
"async-utility", "async-utility",
"flume", "flume",
@@ -3920,7 +3920,7 @@ dependencies = [
[[package]] [[package]]
name = "nostr-relay-pool" name = "nostr-relay-pool"
version = "0.43.0" version = "0.43.0"
source = "git+https://github.com/rust-nostr/nostr#04ca01082044dd4192fee995b9ba101c78af3a02" source = "git+https://github.com/rust-nostr/nostr#b1016f439ef1da5f8fdeae14368f5b7340414389"
dependencies = [ dependencies = [
"async-utility", "async-utility",
"async-wsocket", "async-wsocket",
@@ -3937,7 +3937,7 @@ dependencies = [
[[package]] [[package]]
name = "nostr-sdk" name = "nostr-sdk"
version = "0.43.0" version = "0.43.0"
source = "git+https://github.com/rust-nostr/nostr#04ca01082044dd4192fee995b9ba101c78af3a02" source = "git+https://github.com/rust-nostr/nostr#b1016f439ef1da5f8fdeae14368f5b7340414389"
dependencies = [ dependencies = [
"async-utility", "async-utility",
"nostr", "nostr",
@@ -5051,7 +5051,7 @@ dependencies = [
[[package]] [[package]]
name = "refineable" name = "refineable"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#9c548a0ec6d8b84e2b3b1ee2a78add5fae7a8ba7" source = "git+https://github.com/zed-industries/zed#592b013013e74d5ad44f2c04ef5afeb3be21249e"
dependencies = [ dependencies = [
"derive_refineable", "derive_refineable",
"workspace-hack", "workspace-hack",
@@ -5205,7 +5205,7 @@ dependencies = [
[[package]] [[package]]
name = "reqwest_client" name = "reqwest_client"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#9c548a0ec6d8b84e2b3b1ee2a78add5fae7a8ba7" source = "git+https://github.com/zed-industries/zed#592b013013e74d5ad44f2c04ef5afeb3be21249e"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@@ -5491,9 +5491,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-webpki"
version = "0.103.4" version = "0.103.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" checksum = "b5a37813727b78798e53c2bec3f5e8fe12a6d6f8389bf9ca7802add4c9905ad8"
dependencies = [ dependencies = [
"aws-lc-rs", "aws-lc-rs",
"ring", "ring",
@@ -5740,7 +5740,7 @@ checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749"
[[package]] [[package]]
name = "semantic_version" name = "semantic_version"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#9c548a0ec6d8b84e2b3b1ee2a78add5fae7a8ba7" source = "git+https://github.com/zed-industries/zed#592b013013e74d5ad44f2c04ef5afeb3be21249e"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"serde", "serde",
@@ -6181,7 +6181,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]] [[package]]
name = "sum_tree" name = "sum_tree"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#9c548a0ec6d8b84e2b3b1ee2a78add5fae7a8ba7" source = "git+https://github.com/zed-industries/zed#592b013013e74d5ad44f2c04ef5afeb3be21249e"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"log", "log",
@@ -7080,9 +7080,9 @@ checksum = "ce61d488bcdc9bc8b5d1772c404828b17fc481c0a582b5581e95fb233aef503e"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.18" version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
[[package]] [[package]]
name = "unicode-linebreak" name = "unicode-linebreak"
@@ -7211,7 +7211,7 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]] [[package]]
name = "util" name = "util"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#9c548a0ec6d8b84e2b3b1ee2a78add5fae7a8ba7" source = "git+https://github.com/zed-industries/zed#592b013013e74d5ad44f2c04ef5afeb3be21249e"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-fs", "async-fs",

View File

@@ -216,67 +216,60 @@ impl ChatSpace {
async fn observe_signer() { async fn observe_signer() {
let client = nostr_client(); let client = nostr_client();
let ingester = ingester(); let ingester = ingester();
let stream_timeout = Duration::from_secs(5);
let loop_duration = Duration::from_secs(1); let loop_duration = Duration::from_secs(1);
let mut is_sent_signal = false;
let mut identity: Option<PublicKey> = None;
loop { loop {
if let Some(public_key) = identity { let Ok(signer) = client.signer().await else {
let nip65 = Filter::new().kind(Kind::RelayList).author(public_key); smol::Timer::after(loop_duration).await;
continue;
};
if client.database().count(nip65).await.unwrap_or(0) > 0 { let Ok(public_key) = signer.get_public_key().await else {
let dm_relays = Filter::new().kind(Kind::InboxRelays).author(public_key); smol::Timer::after(loop_duration).await;
continue;
};
match client.database().query(dm_relays).await { // Notify the app that the signer has been set.
Ok(events) => { ingester.send(Signal::SignerSet(public_key)).await;
if let Some(event) = events.first_owned() {
let relay_urls = nip17::extract_relay_list(&event).collect_vec();
if relay_urls.is_empty() { // Subscribe to the NIP-65 relays for the public key.
if !is_sent_signal { let filter = Filter::new()
ingester.send(Signal::DmRelayNotFound).await; .kind(Kind::RelayList)
is_sent_signal = true; .author(public_key)
} .limit(1);
} else {
break; match client
} .stream_events_from(BOOTSTRAP_RELAYS, filter, stream_timeout)
} else if !is_sent_signal { .await
ingester.send(Signal::DmRelayNotFound).await; {
is_sent_signal = true; Ok(mut stream) => {
} else { let mut processed_ids = HashSet::new();
break;
} if let Some(event) = stream.next().await {
} if processed_ids.insert(event.id) {
Err(e) => { // Fetch user's metadata event
log::error!("Database query error: {e}"); Self::fetch_single_event(Kind::Metadata, event.pubkey).await;
if !is_sent_signal {
ingester.send(Signal::DmRelayNotFound).await; // Fetch user's contact list event
is_sent_signal = true; Self::fetch_single_event(Kind::ContactList, event.pubkey).await;
}
} // Fetch user's inbox relays event
} Self::fetch_nip17_relays(event.pubkey).await;
} else {
log::error!("Database error."); break;
break;
}
} else {
// Wait for signer set
if let Ok(signer) = client.signer().await {
if let Ok(public_key) = signer.get_public_key().await {
identity = Some(public_key);
// Notify the app that the signer has been set.
ingester.send(Signal::SignerSet(public_key)).await;
// Subscribe to the NIP-65 relays for the public key.
if let Err(e) = Self::fetch_nip65_relays(public_key).await {
log::error!("Failed to fetch NIP-65 relays: {e}");
} }
} else {
ingester.send(Signal::DmRelayNotFound).await;
} }
} }
} Err(e) => {
log::error!("Error fetching NIP-17 Relay: {e:?}");
ingester.send(Signal::DmRelayNotFound).await;
}
};
smol::Timer::after(loop_duration).await; break;
} }
} }
@@ -395,39 +388,6 @@ impl ChatSpace {
} }
match event.kind { match event.kind {
Kind::RelayList => {
if let Ok(true) = Self::is_self_event(&event).await {
// Fetch user's metadata event
Self::fetch_single_event(Kind::Metadata, event.pubkey).await;
// Fetch user's contact list event
Self::fetch_single_event(Kind::ContactList, event.pubkey).await;
// Fetch user's inbox relays event
Self::fetch_single_event(Kind::InboxRelays, event.pubkey).await;
}
}
Kind::InboxRelays => {
if let Ok(true) = Self::is_self_event(&event).await {
let relays = nip17::extract_relay_list(&event).collect_vec();
if !relays.is_empty() {
for relay in relays.clone().into_iter() {
if client.add_relay(relay).await.is_err() {
let notice = Notice::RelayFailed(relay.clone());
ingester.send(Signal::Notice(notice)).await;
}
if client.connect_relay(relay).await.is_err() {
let notice = Notice::RelayFailed(relay.clone());
ingester.send(Signal::Notice(notice)).await;
}
}
// Subscribe to gift wrap events only in the current user's NIP-17 relays
Self::fetch_gift_wrap(relays, event.pubkey).await;
}
}
}
Kind::ContactList => { Kind::ContactList => {
if let Ok(true) = Self::is_self_event(&event).await { if let Ok(true) = Self::is_self_event(&event).await {
let public_keys = event.tags.public_keys().copied().collect_vec(); let public_keys = event.tags.public_keys().copied().collect_vec();
@@ -610,6 +570,49 @@ impl ChatSpace {
} }
} }
pub async fn fetch_nip17_relays(public_key: PublicKey) {
let client = nostr_client();
let ingester = ingester();
let filter = Filter::new()
.kind(Kind::InboxRelays)
.author(public_key)
.limit(1);
match client.stream_events(filter, Duration::from_secs(5)).await {
Ok(mut stream) => {
let mut processed_ids = HashSet::new();
if let Some(event) = stream.next().await {
if processed_ids.insert(event.id) {
let relays = nip17::extract_relay_list(&event).collect_vec();
if !relays.is_empty() {
for relay in relays.clone().into_iter() {
if client.add_relay(relay).await.is_err() {
let notice = Notice::RelayFailed(relay.clone());
ingester.send(Signal::Notice(notice)).await;
}
if client.connect_relay(relay).await.is_err() {
let notice = Notice::RelayFailed(relay.clone());
ingester.send(Signal::Notice(notice)).await;
}
}
// Subscribe to gift wrap events only in the current user's NIP-17 relays
Self::fetch_gift_wrap(relays, event.pubkey).await;
}
}
} else {
ingester.send(Signal::DmRelayNotFound).await;
}
}
Err(e) => {
log::error!("Error fetching NIP-17 Relay: {e:?}");
ingester.send(Signal::DmRelayNotFound).await;
}
};
}
pub async fn fetch_gift_wrap(relays: Vec<&RelayUrl>, public_key: PublicKey) { pub async fn fetch_gift_wrap(relays: Vec<&RelayUrl>, public_key: PublicKey) {
let client = nostr_client(); let client = nostr_client();
let sub_id = css().gift_wrap_sub_id.clone(); let sub_id = css().gift_wrap_sub_id.clone();
@@ -624,23 +627,6 @@ impl ChatSpace {
} }
} }
/// Fetches NIP-65 relay list for a given public key
pub async fn fetch_nip65_relays(public_key: PublicKey) -> Result<(), Error> {
let client = nostr_client();
let css = css();
let filter = Filter::new()
.kind(Kind::RelayList)
.author(public_key)
.limit(1);
client
.subscribe_to(BOOTSTRAP_RELAYS, filter, css.auto_close_opts)
.await?;
Ok(())
}
/// Fetches metadata for a list of public keys /// Fetches metadata for a list of public keys
async fn fetch_metadata_for_pubkeys(public_keys: HashSet<PublicKey>) { async fn fetch_metadata_for_pubkeys(public_keys: HashSet<PublicKey>) {
if public_keys.is_empty() { if public_keys.is_empty() {