1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-10-18 22:00:23 +00:00

rewrite firstof

This commit is contained in:
2025-09-23 13:37:59 +06:00
parent 2e23f48350
commit 91339fc839
2 changed files with 49 additions and 17 deletions

View File

@@ -32076,7 +32076,8 @@ public final class dev/inmo/tgbotapi/utils/ExtractDataAndJsonFromDecoderKt {
} }
public final class dev/inmo/tgbotapi/utils/FirstOfKt { public final class dev/inmo/tgbotapi/utils/FirstOfKt {
public static final fun firstOf (Lkotlinx/coroutines/CoroutineScope;[Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun firstOf ([Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static final fun firstOfOrNull ([Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
} }
public final class dev/inmo/tgbotapi/utils/IntProgress100Serializer : kotlinx/serialization/KSerializer { public final class dev/inmo/tgbotapi/utils/IntProgress100Serializer : kotlinx/serialization/KSerializer {

View File

@@ -1,26 +1,57 @@
package dev.inmo.tgbotapi.utils package dev.inmo.tgbotapi.utils
import dev.inmo.micro_utils.coroutines.firstOf import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.merge
import kotlin.coroutines.cancellation.CancellationException
/** /**
* Launches all provided suspending [deferreds] in this [CoroutineScope] and returns the value * Executes the given suspend producers in parallel and returns the first successfully produced value, or null
* produced by the first block that completes. * if none of them produce a value.
* *
* - Provide at least one block; otherwise the call will never complete. * Behaviour:
* - Cancellation and error propagation semantics are delegated to the underlying * - All [deferreds] are started concurrently.
* dev.inmo.micro_utils.coroutines.firstOf implementation. * - Failures are ignored except [CancellationException], which is rethrown.
* - As soon as the first value is emitted, upstream flows are cancelled.
* *
* @param T The type of the resulting value. * Notes:
* @param deferreds The suspending blocks to race; they are started eagerly. * - If every producer fails (without throwing [CancellationException]) or none emits a value, this returns null.
* @return The result produced by the first completed block. *
* @param T the type of the produced value
* @param deferreds suspend producers that are started in parallel
* @return the first successfully produced value, or null if none produced a value
* @throws CancellationException if the coroutine scope is cancelled or any producer throws it
*/ */
suspend fun <T> CoroutineScope.firstOf( suspend fun <T> firstOfOrNull(
vararg deferreds: suspend () -> T vararg deferreds: suspend () -> T
): T = firstOf { ): T? {
deferreds.forEach { val resultFlow = deferreds.map {
add { flow {
it() runCatching {
it()
}.onSuccess {
emit(it)
}.onFailure {
if (it is CancellationException) throw it
}
} }
} }.merge()
return resultFlow.firstOrNull()
}
/**
* Executes the given suspend producers in parallel and returns the first successfully produced value.
*
* This is a non-nullable variant of [firstOfOrNull]. If no producer yields a value, it throws an [IllegalStateException].
*
* @param T the type of the produced value
* @param deferreds suspend producers that are started in parallel
* @return the first successfully produced value
* @throws IllegalStateException if none of the producers yielded a value
* @throws CancellationException if the coroutine scope is cancelled or any producer throws it
*/
suspend fun <T> firstOf(
vararg deferreds: suspend () -> T
): T {
return firstOfOrNull(*deferreds) ?: error("Unable to get result of deferreds")
} }