Helio
11/27/2023, 3:04 AMHttpRequestRetry
. I was trying to create a mechanism to retry on ConnectionTimeoutException, more specifically like:
install(HttpRequestRetry) {
maxRetries = 5
retryOnServerErrors()
retryOnExceptionIf() { _, cause ->
cause is ConnectTimeoutException
}
exponentialDelay()
}
However, from what I can tell, it never retries and it fails immediately, even though the endpoint is returning ConnectionTimeoutException. I noticed a couple of issues reported: Issue_1, Issue_2 and I thought that it could be related since I'm also making usage of HttpTimeout
plugin.
install(HttpTimeout) {
requestTimeoutMillis = 30_000
connectTimeoutMillis = 10_000
}
As part of the tests, I also tried to replace retryOnExceptionIf
with retryOnException(retryOnTimeout=true)
but no success.
Would any of you be able to kindly provide any insights on the why it does not work? Any help is greatly appreciated.Aleksei Tirman [JB]
11/27/2023, 10:57 AMinstall(HttpRequestRetry) {
maxRetries = 5
retryOnServerErrors()
retryOnException(5, true) // this line configures retrying on ConnectTimeoutException
exponentialDelay()
}
Helio
11/27/2023, 10:58 AMHelio
11/27/2023, 11:24 AMget("/route") {
runCatching {
MyService.doSomething()
}.onFailure {
call.respond(HttpStatusCode.InternalServerError)
}.onSuccess {
call.respond(HttpStatusCode.OK)
}.getOrNull()
}
suspend fun doSomething() {
createFlowToDoSomething().retry(5) {
logger.warn("Failed to create flow. :(")
delay(Duration.ofSeconds(3))
it is IllegalStateException
//If I add it is ConnectionTimetoutException, the retries work... But not from the CIOEngine.
}.collect()
}
private fun createFlowToDoSomething() : Flow<Unit> {
return flow<Unit> {
val result =
MyKtorCIOHTTPClient.sendRequestToServer() //If the request fail with ConnectionTimeout, it is not retried.
}.flowOn(<http://Dispatchers.IO|Dispatchers.IO>)
}
//This is how I'm trying to force the ConnectionTimeoutException to be thrown. (Test purposes of course)
suspend fun sendRequestToServer () {
throw ConnectTimeoutException("dummy_url")
}
Helio
11/27/2023, 11:25 AMprivate val client = HttpClient(CIO) {
expectSuccess = true
engine {
endpoint {
maxConnectionsPerRoute = 500
}
}
install(HttpRequestRetry) {
<http://logger.info|logger.info>("Retrying...")
maxRetries = 5
retryOnServerErrors()
retryOnException(5, true) // this line configures retrying on ConnectTimeoutException
exponentialDelay()
<http://logger.info|logger.info>("Finished retry")
}
install(ContentNegotiation) {
json(Json {
ignoreUnknownKeys = true
})
}
install(HttpTimeout) {
requestTimeoutMillis = 30_000
connectTimeoutMillis = 10_000
}
defaultRequest {
url {
protocol = myHost.protocol
port = myHost.port
host = myHost.host
}
headers {
append("Authorization", "Bearer $adminToken")
}
}
}
Helio
11/28/2023, 6:40 AMAleksei Tirman [JB]
11/28/2023, 9:15 AMretryOnException(5, true)
line make any difference? How do you reproduce the connection timeout? Does it work without any other plugins?Helio
11/28/2023, 9:19 AM//This is how I'm trying to force the ConnectionTimeoutException to be thrown. (Test purposes of course)
suspend fun sendRequestToServer () {
throw ConnectTimeoutException("dummy_url")
}
Helio
11/28/2023, 9:19 AMretryOnException
, but it didn't make any difference. 😞Aleksei Tirman [JB]
11/28/2023, 9:23 AM10.255.255.1
)?Helio
11/28/2023, 9:24 AMHelio
11/28/2023, 9:43 AMHelio
11/28/2023, 10:24 AMConnectionTimeout
, the request still waits for a response? And the RequestTimeout is also triggered... does it means we need to handle the cancelation as well? Just trying to understand the behaviour... I understand the retries, but what about those HttpTimeouts?
2023-11-28 20:47:21.349 [DefaultDispatcher-worker-1] TRACE i.ktor.client.plugins.HttpPlainText - Adding Accept-Charset=UTF-8 to <http://10.255.255.1:8080/something>
2023-11-28 20:47:25.891 [DefaultDispatcher-worker-1] TRACE i.k.client.plugins.HttpRequestRetry - Retrying request <http://10.255.255.1:8080/something> attempt: 1
2023-11-28 20:47:32.862 [DefaultDispatcher-worker-4] TRACE i.k.client.plugins.HttpRequestRetry - Retrying request <http://10.255.255.1:8080/something> attempt: 2
2023-11-28 20:47:43.590 [DefaultDispatcher-worker-2] TRACE i.k.client.plugins.HttpRequestRetry - Retrying request <http://10.255.255.1:8080/something> attempt: 3
2023-11-28 20:47:51.356 [DefaultDispatcher-worker-4] TRACE io.ktor.client.plugins.HttpTimeout - Request timeout: <http://10.255.255.1:8080/something>
2023-11-28 20:47:55.891 [DefaultDispatcher-worker-4] TRACE io.ktor.client.plugins.HttpTimeout - Request timeout: <http://10.255.255.1:8080/something>
2023-11-28 20:48:02.537 [DefaultDispatcher-worker-4] TRACE i.k.client.plugins.HttpRequestRetry - Retrying request <http://10.255.255.1:8080/something> attempt: 4
2023-11-28 20:48:02.864 [DefaultDispatcher-worker-4] TRACE io.ktor.client.plugins.HttpTimeout - Request timeout: <http://10.255.255.1:8080/something>
2023-11-28 20:48:13.591 [DefaultDispatcher-worker-3] TRACE io.ktor.client.plugins.HttpTimeout - Request timeout: <http://10.255.255.1:8080/something>
2023-11-28 20:48:32.540 [DefaultDispatcher-worker-5] TRACE io.ktor.client.plugins.HttpTimeout - Request timeout: <http://10.255.255.1:8080/something>
2023-11-28 20:48:36.875 [DefaultDispatcher-worker-3] TRACE i.k.client.plugins.HttpRequestRetry - Retrying request <http://10.255.255.1:8080/something> attempt: 5
Aleksei Tirman [JB]
11/28/2023, 10:34 AMHelio
11/28/2023, 10:36 AMAleksei Tirman [JB]
11/28/2023, 10:42 AMHelio
11/28/2023, 11:00 AMHelio
11/28/2023, 11:01 AM