From ad624031bf1ce0d447f58a7a2596b3dfec964ef2 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 20 Apr 2026 11:15:09 -0400 Subject: [PATCH] Improves the FetchFirst to not fail in the first eose from the first relay. --- .../accessories/NostrClientFetchFirstExt.kt | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/NostrClientFetchFirstExt.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/NostrClientFetchFirstExt.kt index 16aa65034..fb1ab9a85 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/NostrClientFetchFirstExt.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/NostrClientFetchFirstExt.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED +import kotlinx.coroutines.selects.select import kotlinx.coroutines.withTimeoutOrNull suspend fun INostrClient.fetchFirst( @@ -66,8 +67,11 @@ suspend fun INostrClient.fetchFirst( suspend fun INostrClient.fetchFirst( subscriptionId: String = newSubId(), filters: Map>, + timeoutMs: Long = 30_000L, ): Event? { - val resultChannel = Channel(UNLIMITED) + val eventChannel = Channel(UNLIMITED) + val doneChannel = Channel(UNLIMITED) + val remaining = filters.keys.toMutableSet() val listener = object : SubscriptionListener { @@ -77,7 +81,7 @@ suspend fun INostrClient.fetchFirst( relay: NormalizedRelayUrl, forFilters: List?, ) { - resultChannel.trySend(event) + eventChannel.trySend(event) } override fun onCannotConnect( @@ -85,7 +89,7 @@ suspend fun INostrClient.fetchFirst( message: String, forFilters: List?, ) { - resultChannel.trySend(null) + doneChannel.trySend(relay) } override fun onClosed( @@ -93,29 +97,39 @@ suspend fun INostrClient.fetchFirst( relay: NormalizedRelayUrl, forFilters: List?, ) { - resultChannel.trySend(null) + doneChannel.trySend(relay) } override fun onEose( relay: NormalizedRelayUrl, forFilters: List?, ) { - resultChannel.trySend(null) + doneChannel.trySend(relay) } } - val result = - try { - subscribe(subscriptionId, filters, listener) + var result: Event? = null + try { + subscribe(subscriptionId, filters, listener) - withTimeoutOrNull(30000) { - resultChannel.receive() + withTimeoutOrNull(timeoutMs) { + while (remaining.isNotEmpty()) { + select { + eventChannel.onReceive { event -> + result = event + remaining.clear() + } + doneChannel.onReceive { relay -> + remaining.remove(relay) + } + } } - } finally { - unsubscribe(subscriptionId) } - - resultChannel.close() + } finally { + unsubscribe(subscriptionId) + eventChannel.close() + doneChannel.close() + } return result }