From c1374c118d7cf9d65339a697c17a6d781c6941a7 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 19 Sep 2022 01:39:23 +0600 Subject: [PATCH] Improve support of new exceptions recovering mechanism --- CHANGELOG.md | 3 ++ .../bot/exceptions/RequestException.kt | 43 ++++++++++++++----- .../tgbotapi/bot/ktor/KtorRequestsExecutor.kt | 30 +++++++------ .../utils/updates/retrieving/LongPolling.kt | 11 +++-- 4 files changed, 56 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72fb3fa764..2980780c81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## 3.2.5 +* `Common`: + * Improve support of new exceptions recovering mechanism + ## 3.2.4 * `API`: diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/exceptions/RequestException.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/exceptions/RequestException.kt index 7448d2e901..439af142ed 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/exceptions/RequestException.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/exceptions/RequestException.kt @@ -4,6 +4,7 @@ import com.soywiz.klock.DateTime import dev.inmo.tgbotapi.types.Response import dev.inmo.tgbotapi.types.RetryAfterError import io.ktor.utils.io.errors.IOException +import kotlinx.coroutines.CopyableThrowable fun newRequestException( response: Response, @@ -35,9 +36,11 @@ fun newRequestException( } } ?: CommonRequestException(response, plainAnswer, message, cause) -sealed class BotException(message: String = "Something went wrong", cause: Throwable? = null) : IOException(message, cause) +sealed class BotException(message: String = "Something went wrong", cause: Throwable? = null) : IOException(message, cause), CopyableThrowable -class CommonBotException(message: String = "Something went wrong", cause: Throwable? = null) : BotException(message, cause) +class CommonBotException(message: String = "Something went wrong", cause: Throwable? = null) : BotException(message, cause) { + override fun createCopy(): BotException = CommonBotException(message!!, cause) +} sealed class RequestException constructor( val response: Response, @@ -50,28 +53,46 @@ sealed class RequestException constructor( ) class CommonRequestException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = CommonRequestException(response, plainAnswer, message, cause) +} class UnauthorizedException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = UnauthorizedException(response, plainAnswer, message, cause) +} class ReplyMessageNotFoundException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = ReplyMessageNotFoundException(response, plainAnswer, message, cause) +} class MessageIsNotModifiedException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = MessageIsNotModifiedException(response, plainAnswer, message, cause) +} class MessageToEditNotFoundException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = MessageToEditNotFoundException(response, plainAnswer, message, cause) +} class InvalidPhotoDimensionsException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = InvalidPhotoDimensionsException(response, plainAnswer, message, cause) +} class WrongFileIdentifierException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = WrongFileIdentifierException(response, plainAnswer, message, cause) +} class TooMuchRequestsException(val retryAfter: RetryAfterError, response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = TooMuchRequestsException(retryAfter, response, plainAnswer, message, cause) +} class GetUpdatesConflict(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = GetUpdatesConflict(response, plainAnswer, message, cause) +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutor.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutor.kt index 03ab290421..c9a3663fe5 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutor.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutor.kt @@ -77,21 +77,23 @@ class KtorRequestsExecutor( val result = it.exceptionOrNull() ?.let { e -> pipelineStepsHolder.onRequestException(request, e) ?.let { return@let it } - if (e is ClientRequestException) { - val exceptionResult = runCatchingSafely { - val content = e.response.bodyAsText() - val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content) - newRequestException( - responseObject, - content, - "Can't get result object from $content" - ) + when (e) { + is ClientRequestException -> { + val exceptionResult = runCatchingSafely { + val content = e.response.bodyAsText() + val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content) + newRequestException( + responseObject, + content, + "Can't get result object from $content" + ) + } + exceptionResult.exceptionOrNull() ?.let { + CommonBotException(cause = e) + } ?: exceptionResult.getOrThrow() } - exceptionResult.exceptionOrNull() ?.let { - CommonBotException(cause = e) - } ?: exceptionResult.getOrThrow() - } else { - CommonBotException(cause = e) + is BotException -> e + else -> CommonBotException(cause = e) } } ?.let { Result.failure(it) } ?: it pipelineStepsHolder.onRequestReturnResult(result, request, callsFactories) 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 830f37f0c3..3e9f27dfaa 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 @@ -3,8 +3,7 @@ package dev.inmo.tgbotapi.extensions.utils.updates.retrieving import dev.inmo.micro_utils.coroutines.* import dev.inmo.tgbotapi.bot.RequestsExecutor import dev.inmo.tgbotapi.bot.TelegramBot -import dev.inmo.tgbotapi.bot.exceptions.GetUpdatesConflict -import dev.inmo.tgbotapi.bot.exceptions.RequestException +import dev.inmo.tgbotapi.bot.exceptions.* import dev.inmo.tgbotapi.extensions.utils.updates.convertWithMediaGroupUpdates import dev.inmo.tgbotapi.extensions.utils.updates.lastUpdateIdentifier import dev.inmo.tgbotapi.requests.GetUpdates @@ -101,10 +100,10 @@ fun TelegramBot.createAccumulatedUpdatesRetrieverFlow( ): Flow = longPollingFlow( timeoutSeconds = 0, exceptionsHandler = { - if (it is HttpRequestTimeoutException) { - throw CancellationException("Cancel due to absence of new updates") - } else { - exceptionsHandler ?.invoke(it) + when { + it is HttpRequestTimeoutException || + (it is CommonBotException && it.cause is HttpRequestTimeoutException) -> throw CancellationException("Cancel due to absence of new updates") + else -> exceptionsHandler ?.invoke(it) } }, allowedUpdates = allowedUpdates