Replace flume Selector with futures select for wasm compatibility

This commit is contained in:
2026-10-25 10:31:53 +07:00
parent d7ae86e955
commit 72794dcbdc
5 changed files with 44 additions and 23 deletions
Generated
+1
View File
@@ -5719,6 +5719,7 @@ dependencies = [
"anyhow", "anyhow",
"common", "common",
"flume 0.11.1", "flume 0.11.1",
"futures",
"gpui-pre", "gpui-pre",
"instant", "instant",
"log", "log",
+5
View File
@@ -9,3 +9,8 @@ gpui.workspace = true
anyhow.workspace = true anyhow.workspace = true
rust-embed.workspace = true rust-embed.workspace = true
gpui-kit.workspace = true gpui-kit.workspace = true
# On wasm there is no filesystem to read from, so rust-embed's debug-mode
# disk loading returns nothing; embed the assets even in debug builds.
[target.'cfg(target_arch = "wasm32")'.dependencies]
rust-embed = { workspace = true, features = ["debug-embed"] }
+1
View File
@@ -8,6 +8,7 @@ publish.workspace = true
common = { path = "../common" } common = { path = "../common" }
state = { path = "../state" } state = { path = "../state" }
futures.workspace = true
gpui.workspace = true gpui.workspace = true
nostr-sdk.workspace = true nostr-sdk.workspace = true
instant.workspace = true instant.workspace = true
+35 -16
View File
@@ -3,7 +3,10 @@ use std::sync::RwLock;
use anyhow::{Error, anyhow}; use anyhow::{Error, anyhow};
use common::emojis_from_tags; use common::emojis_from_tags;
use gpui::{App, AppContext, Context, Entity, EventEmitter, Global, Subscription, Task}; use futures::{FutureExt, pin_mut};
use gpui::{
App, AppContext, BackgroundExecutor, Context, Entity, EventEmitter, Global, Subscription, Task,
};
use instant::Duration; use instant::Duration;
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
use smallvec::{SmallVec, smallvec}; use smallvec::{SmallVec, smallvec};
@@ -98,8 +101,9 @@ impl PersonRegistry {
})); }));
let client3 = client.clone(); let client3 = client.clone();
let executor = cx.background_executor().clone();
tasks.push(cx.background_spawn(async move { tasks.push(cx.background_spawn(async move {
Self::handle_requests(&client3, &metadata_rx).await; Self::handle_requests(&client3, &metadata_rx, executor).await;
})); }));
tasks.push(cx.spawn(async move |this, cx| { tasks.push(cx.spawn(async move |this, cx| {
@@ -193,30 +197,45 @@ impl PersonRegistry {
} }
/// Handle request for metadata /// Handle request for metadata
async fn handle_requests(client: &Client, rx: &flume::Receiver<PublicKey>) { async fn handle_requests(
client: &Client,
rx: &flume::Receiver<PublicKey>,
executor: BackgroundExecutor,
) {
let mut batch: HashSet<PublicKey> = HashSet::new(); let mut batch: HashSet<PublicKey> = HashSet::new();
loop { loop {
match flume::Selector::new() let timer = executor.timer(Duration::from_secs(TIMEOUT)).fuse();
.recv(rx, |result| result.ok()) pin_mut!(timer);
.wait_timeout(Duration::from_secs(TIMEOUT))
{ let request = futures::select! {
Ok(Some(public_key)) => { result = rx.recv_async().fuse() => match result {
batch.insert(public_key); Ok(public_key) => public_key,
// Process the batch if it's full Err(_) => {
if batch.len() >= 20 if !batch.is_empty()
&& let Err(e) = get_metadata(client, std::mem::take(&mut batch)).await && let Err(e) = get_metadata(client, std::mem::take(&mut batch)).await
{ {
log::warn!("Failed to get metadata batch: {e}"); log::warn!("Failed to get metadata batch: {e}");
}
return;
} }
} },
_ => { () = timer => {
if !batch.is_empty() if !batch.is_empty()
&& let Err(e) = get_metadata(client, std::mem::take(&mut batch)).await && let Err(e) = get_metadata(client, std::mem::take(&mut batch)).await
{ {
log::warn!("Failed to get metadata batch: {e}"); log::warn!("Failed to get metadata batch: {e}");
} }
continue;
} }
};
batch.insert(request);
// Process the batch if it's full
if batch.len() >= 20
&& let Err(e) = get_metadata(client, std::mem::take(&mut batch)).await
{
log::warn!("Failed to get metadata batch: {e}");
} }
} }
} }
+2 -7
View File
@@ -1,8 +1,7 @@
use std::time::{SystemTime, UNIX_EPOCH};
use gpui::{AnyElement, App, IntoElement, ParentElement, SharedString, Styled, Window, img}; use gpui::{AnyElement, App, IntoElement, ParentElement, SharedString, Styled, Window, img};
use gpui_kit::component::button::{Button, ButtonVariants}; use gpui_kit::component::button::{Button, ButtonVariants};
use gpui_kit::component::v_flex; use gpui_kit::component::v_flex;
use instant::Instant;
use crate::dialogs::import; use crate::dialogs::import;
@@ -11,12 +10,8 @@ const SIGNED_OUT_BANNERS: [&str; 2] = ["brand/bg1.jpg", "brand/bg2.jpg"];
/// Pick one of the signed-out backgrounds at random. /// Pick one of the signed-out backgrounds at random.
pub(super) fn pick_banner() -> SharedString { pub(super) fn pick_banner() -> SharedString {
let nanos = SystemTime::now() let nanos = Instant::now().elapsed().subsec_nanos();
.duration_since(UNIX_EPOCH)
.map(|elapsed| elapsed.subsec_nanos())
.unwrap_or_default();
let index = nanos as usize % SIGNED_OUT_BANNERS.len(); let index = nanos as usize % SIGNED_OUT_BANNERS.len();
SIGNED_OUT_BANNERS[index].into() SIGNED_OUT_BANNERS[index].into()
} }