From 2ba447b1262d2b691221cbd36ed06373f94e645d Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 21 Jul 2025 20:41:51 +0600 Subject: [PATCH] fix of cancellation exception throwing? --- .gitignore | 1 + tgbotapi.core/api/tgbotapi.core.api | 5 +++++ .../ktor/base/DefaultKtorRequestsExecutor.kt | 5 ++++- .../tgbotapi/utils/CausedByCancellation.kt | 18 ++++++++++++++++++ .../dev/inmo/tgbotapi/utils/DefaultKSLog.kt | 2 +- .../utils/updates/retrieving/LongPolling.kt | 4 +++- 6 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/CausedByCancellation.kt diff --git a/.gitignore b/.gitignore index 72f7a6bb59..7fc9690878 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ settings.xml .gradle/ build/ out/ +bin/ local.properties kotlin-js-store/ diff --git a/tgbotapi.core/api/tgbotapi.core.api b/tgbotapi.core/api/tgbotapi.core.api index 8dfdadffa8..493cc8a123 100644 --- a/tgbotapi.core/api/tgbotapi.core.api +++ b/tgbotapi.core/api/tgbotapi.core.api @@ -30491,6 +30491,11 @@ public final class dev/inmo/tgbotapi/utils/ByteReadChannelAllocatorDeserializati public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; } +public final class dev/inmo/tgbotapi/utils/CausedByCancellationKt { + public static final fun causedCancellationException (Ljava/lang/Throwable;)Ljava/util/concurrent/CancellationException; + public static final fun isCausedByCancellation (Ljava/lang/Throwable;)Z +} + public final class dev/inmo/tgbotapi/utils/DefaultKSLogKt { public static final fun SetDefaultKTgBotAPIKSLog (ZLkotlin/jvm/functions/Function1;)V public static synthetic fun SetDefaultKTgBotAPIKSLog$default (ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DefaultKtorRequestsExecutor.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DefaultKtorRequestsExecutor.kt index 670cbf6215..d2c683f09d 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DefaultKtorRequestsExecutor.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DefaultKtorRequestsExecutor.kt @@ -1,6 +1,7 @@ package dev.inmo.tgbotapi.bot.ktor.base import dev.inmo.kslog.common.* +import dev.inmo.micro_utils.coroutines.runCatchingLogging import dev.inmo.tgbotapi.bot.BaseRequestsExecutor import dev.inmo.tgbotapi.bot.exceptions.BotException import dev.inmo.tgbotapi.bot.exceptions.CommonBotException @@ -16,6 +17,7 @@ import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper import io.ktor.client.* import io.ktor.client.plugins.* import io.ktor.client.statement.* +import kotlinx.coroutines.CancellationException import kotlinx.serialization.json.Json class DefaultKtorRequestsExecutor internal constructor( @@ -47,7 +49,7 @@ class DefaultKtorRequestsExecutor internal constructor( } override suspend fun execute(request: Request): T { - return runCatching { + return runCatchingLogging(logger = logger) { logger.v { "Start request $request" } pipelineStepsHolder.onBeforeSearchCallFactory(request, callsFactories) requestsLimiter.limit(request) { @@ -95,6 +97,7 @@ class DefaultKtorRequestsExecutor internal constructor( CommonBotException(cause = e) } ?: exceptionResult.getOrThrow() } + is CancellationException, is BotException -> e else -> CommonBotException(cause = e) }.also { newException -> diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/CausedByCancellation.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/CausedByCancellation.kt new file mode 100644 index 0000000000..3b65f8071e --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/CausedByCancellation.kt @@ -0,0 +1,18 @@ +package dev.inmo.tgbotapi.utils + +import kotlinx.coroutines.CancellationException + +fun Throwable.causedCancellationException(): CancellationException? { + var current = this + while (current !is CancellationException) { + when { + // It is possible, that API will be changed and cancellation will be caused by something else + current is CancellationException && current.cause == null -> return current + else -> current = current.cause ?: return null + } + } + + return current +} + +fun Throwable.isCausedByCancellation(): Boolean = causedCancellationException() == null diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/DefaultKSLog.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/DefaultKSLog.kt index d781274496..c53d50d864 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/DefaultKSLog.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/DefaultKSLog.kt @@ -19,7 +19,7 @@ private inline fun CreateDefaultKSLogger( ): KSLog { val filter: MessageFilter? = if (dropCancellationExceptions) { { ll, message, e -> - e !is CancellationException + e ?.isCausedByCancellation() != true } } else { null diff --git a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/updates/retrieving/LongPolling.kt b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/updates/retrieving/LongPolling.kt index 1e96de595f..da18e877a6 100644 --- a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/updates/retrieving/LongPolling.kt +++ b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/updates/retrieving/LongPolling.kt @@ -15,6 +15,8 @@ import dev.inmo.tgbotapi.types.update.abstracts.BaseSentMessageUpdate import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.updateshandlers.* import dev.inmo.tgbotapi.utils.DefaultKTgBotAPIKSLog +import dev.inmo.tgbotapi.utils.causedCancellationException +import dev.inmo.tgbotapi.utils.isCausedByCancellation import dev.inmo.tgbotapi.utils.subscribeWithBotLogger import io.ktor.client.plugins.HttpRequestTimeoutException import io.ktor.utils.io.CancellationException @@ -106,7 +108,7 @@ fun TelegramBot.longPollingFlow( } } }.onFailure { - if (it is CancellationException) { + it.causedCancellationException() ?.let { cancel(it) } }