mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-10 08:27:04 +00:00
fix: drain buffered event on EOSE in fetchFirst to avoid race
A relay sends its matching events before its EOSE, so both an event and the relay's completion can sit buffered in their channels at the same time. The select() over the two channels picks a ready clause at random, so it could process the doneChannel completion first, empty `remaining`, and exit the loop while the matching event was still unread — returning null instead of the event. On a relay completion, drain the event channel first and treat any already-buffered event as the result before marking the relay done.
This commit is contained in:
+11
-1
@@ -120,7 +120,17 @@ suspend fun INostrClient.fetchFirst(
|
||||
remaining.clear()
|
||||
}
|
||||
doneChannel.onReceive { relay ->
|
||||
remaining.remove(relay)
|
||||
// A relay sends its matching events before its EOSE, so an event may
|
||||
// already be buffered when this completion fires. select() picks a ready
|
||||
// clause at random, so without this drain we could treat the relay as done
|
||||
// and exit while its event still sits unread in the channel.
|
||||
val buffered = eventChannel.tryReceive().getOrNull()
|
||||
if (buffered != null) {
|
||||
result = buffered
|
||||
remaining.clear()
|
||||
} else {
|
||||
remaining.remove(relay)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user