update per event kind

This commit is contained in:
2026-09-27 08:34:13 +07:00
parent 4d2d058396
commit c170c4a800
6 changed files with 75 additions and 63 deletions
+48 -16
View File
@@ -37,9 +37,10 @@ pub enum BackendEvent {
PassphraseRequired,
/// The signer changed on login, logout or account switch.
SignerChanged,
/// Events received from a relay, including this client's own events echoed
/// back by a relay after publishing.
NostrUpdate(Vec<Update>),
/// Kind-0 metadata arrived for these authors; re-read them from the store.
ProfileUpdates(Vec<PublicKey>),
/// Repository events arrived: announcements, states, activity and deletions.
RepoUpdates(Vec<Update>),
Synced,
SyncProgress {
total: u64,
@@ -89,12 +90,16 @@ impl Backend {
let pump: Task<Result<(), Error>> = cx.spawn(async move |this, cx| {
let mut notifications = pump_client.notifications();
let mut pending: Vec<Update> = Vec::new();
let mut pending_profiles: HashSet<PublicKey> = HashSet::new();
let mut pending_repos: Vec<Update> = Vec::new();
let mut seen: HashSet<EventId> = HashSet::new();
'outer: loop {
match next_update(&mut notifications, &mut seen).await {
Some(update) => pending.push(update),
Some(UpdateEvent::Profile(author)) => {
pending_profiles.insert(author);
}
Some(UpdateEvent::Repo(update)) => pending_repos.push(update),
None => break,
}
@@ -114,18 +119,29 @@ impl Backend {
futures::pin_mut!(next);
match futures::future::select(next, timer).await {
futures::future::Either::Left((Some(update), _)) => pending.push(update),
futures::future::Either::Left((Some(UpdateEvent::Profile(author)), _)) => {
pending_profiles.insert(author);
}
futures::future::Either::Left((Some(UpdateEvent::Repo(update)), _)) => {
pending_repos.push(update);
}
futures::future::Either::Left((None, _)) => break 'outer,
futures::future::Either::Right(_) => break,
}
}
let batch = std::mem::take(&mut pending);
let profiles: Vec<PublicKey> = pending_profiles.drain().collect();
let repos = std::mem::take(&mut pending_repos);
if let Err(e) =
this.update(cx, |_this, cx| cx.emit(BackendEvent::NostrUpdate(batch)))
{
log::warn!("failed to emit nostr update: {e}");
if let Err(e) = this.update(cx, |_this, cx| {
if !profiles.is_empty() {
cx.emit(BackendEvent::ProfileUpdates(profiles));
}
if !repos.is_empty() {
cx.emit(BackendEvent::RepoUpdates(repos));
}
}) {
log::warn!("failed to emit backend update: {e}");
}
}
@@ -1298,18 +1314,34 @@ impl Backend {
}
}
/// A relay event the backend routes to a store group.
enum UpdateEvent {
Profile(PublicKey),
Repo(Update),
}
/// Await the next relay event from the notification stream.
async fn next_update(
notifications: &mut (impl futures::Stream<Item = ClientNotification> + Unpin),
seen: &mut HashSet<EventId>,
) -> Option<Update> {
) -> Option<UpdateEvent> {
loop {
match notifications.next().await {
Some(ClientNotification::Message { message, .. }) => {
if let RelayMessage::Event { event, .. } = *message
&& seen.insert(event.id)
{
return Some(Update::from_event(&event));
let RelayMessage::Event { event, .. } = *message else {
continue;
};
let update = match event.kind {
Kind::Metadata => UpdateEvent::Profile(event.pubkey),
kind if filters::is_repo_kind(kind) => {
UpdateEvent::Repo(Update::from_event(&event))
}
_ => continue,
};
if seen.insert(event.id) {
return Some(update);
}
}
Some(_) => continue,