1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-11-26 03:58:44 +00:00

suspend inline function handleSafely was added

This commit is contained in:
InsanusMokrassar 2020-04-13 12:40:14 +06:00
parent 7668c48081
commit 8c76283db5
4 changed files with 108 additions and 80 deletions

View File

@ -50,6 +50,9 @@
case will be created `UnknownUpdateType` case will be created `UnknownUpdateType`
* `UnknownUpdateType$rawJson` value now is included (`JsonElement`) * `UnknownUpdateType$rawJson` value now is included (`JsonElement`)
* **EXPERIMENTALLY** `BaseEditMessageUpdate#data` now is `CommonMessage<*>` * **EXPERIMENTALLY** `BaseEditMessageUpdate#data` now is `CommonMessage<*>`
* Suspend inline function `handleSafely` was added
* `KtorRequestsExecutor` now use `handleSafely` instead of `try` with `supervisorScope`
* `UpdatesPolling` now use `handleSafely` instead of `try` with `supervisorScope`
### 0.26.2 ### 0.26.2

View File

@ -11,6 +11,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update
import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.* import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.*
import com.github.insanusmokrassar.TelegramBotAPI.utils.PreviewFeature import com.github.insanusmokrassar.TelegramBotAPI.utils.PreviewFeature
import com.github.insanusmokrassar.TelegramBotAPI.utils.handleSafely
import io.ktor.client.features.HttpRequestTimeoutException import io.ktor.client.features.HttpRequestTimeoutException
import kotlinx.coroutines.* import kotlinx.coroutines.*
@ -24,8 +25,18 @@ fun RequestsExecutor.startGettingOfUpdates(
var lastUpdateIdentifier: UpdateIdentifier? = null var lastUpdateIdentifier: UpdateIdentifier? = null
while (isActive) { while (isActive) {
try { handleSafely(
supervisorScope { { e ->
when (e) {
is HttpRequestTimeoutException -> exceptionsHandler ?.invoke(e)
is RequestException -> {
exceptionsHandler ?.invoke(e)
delay(1000L)
}
else -> exceptionsHandler ?.invoke(e)
}
}
) {
val updates = getUpdates( val updates = getUpdates(
offset = lastUpdateIdentifier?.plus(1), offset = lastUpdateIdentifier?.plus(1),
timeout = timeoutSeconds, timeout = timeoutSeconds,
@ -45,7 +56,7 @@ fun RequestsExecutor.startGettingOfUpdates(
} }
} }
supervisorScope { handleSafely {
for (update in updates) { for (update in updates) {
updatesReceiver(update) updatesReceiver(update)
@ -53,14 +64,6 @@ fun RequestsExecutor.startGettingOfUpdates(
} }
} }
} }
} catch (e: HttpRequestTimeoutException) {
exceptionsHandler ?.invoke(e) // it is ok due to mechanism of long polling
} catch (e: RequestException) {
exceptionsHandler ?.invoke(e) // it is not ok, but in most cases it will mean that there is some limit for requests count
delay(1000L)
} catch (e: Exception) {
exceptionsHandler ?.invoke(e)
}
} }
} }

View File

@ -9,7 +9,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.bot.settings.limiters.RequestL
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
import com.github.insanusmokrassar.TelegramBotAPI.types.Response import com.github.insanusmokrassar.TelegramBotAPI.types.Response
import com.github.insanusmokrassar.TelegramBotAPI.types.RetryAfterError import com.github.insanusmokrassar.TelegramBotAPI.types.RetryAfterError
import com.github.insanusmokrassar.TelegramBotAPI.utils.TelegramAPIUrlsKeeper import com.github.insanusmokrassar.TelegramBotAPI.utils.*
import com.github.insanusmokrassar.TelegramBotAPI.utils.nonstrictJsonFormat import com.github.insanusmokrassar.TelegramBotAPI.utils.nonstrictJsonFormat
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.call.receive import io.ktor.client.call.receive
@ -17,7 +17,6 @@ import io.ktor.client.features.*
import io.ktor.client.statement.HttpStatement import io.ktor.client.statement.HttpStatement
import io.ktor.client.statement.readText import io.ktor.client.statement.readText
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.supervisorScope
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
class KtorRequestsExecutor( class KtorRequestsExecutor(
@ -43,8 +42,21 @@ class KtorRequestsExecutor(
} }
override suspend fun <T : Any> execute(request: Request<T>): T { override suspend fun <T : Any> execute(request: Request<T>): T {
return try { return handleSafely(
supervisorScope { { e ->
throw if (e is ClientRequestException) {
val content = e.response.readText()
val responseObject = jsonFormatter.parse(Response.serializer(), content)
newRequestException(
responseObject,
content,
"Can't get result object from $content"
)
} else {
e
}
}
) {
requestsLimiter.limit { requestsLimiter.limit {
var statement: HttpStatement? = null var statement: HttpStatement? = null
for (factory in callsFactories) { for (factory in callsFactories) {
@ -81,17 +93,6 @@ class KtorRequestsExecutor(
}) })
} }
} }
} catch (e: ClientRequestException) {
val content = e.response.readText()
val responseObject = jsonFormatter.parse(Response.serializer(), content)
throw newRequestException(
responseObject,
content,
"Can't get result object from $content"
)
} catch (e: Exception) {
throw e
}
} }
override fun close() { override fun close() {

View File

@ -0,0 +1,21 @@
package com.github.insanusmokrassar.TelegramBotAPI.utils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.supervisorScope
/**
* It will run [block] inside of [supervisorScope] to avoid problems with catching of exceptions
*
* @param [onException] Will be called when happen exception inside of [block]. By default will throw exception - this
* exception will be available for catching
*/
suspend inline fun <T> handleSafely(
noinline onException: suspend (Exception) -> T = { throw it },
noinline block: suspend CoroutineScope.() -> T
): T {
return try {
supervisorScope(block)
} catch (e: Exception) {
onException(e)
}
}