Alexander Weickmann
07/29/2019, 8:34 AMobject HttpApi {
private val httpClient = httpClient {
it.followRedirects = false
}
private suspend fun <T> httpClientWithLogin(work: suspend (HttpClient) -> T): T {
httpClient.login()
return work(httpClient)
}
suspend fun someApiMethod(): Result = httpClientWithLogin { client ->
...
}
}
The problem is, that the httpClient might become unusable, e.g. because it is closed for whatever reason. I want to protect against that by recreating the httpClient instance. So I am doing this:
object HttpApi {
private var httpClient = recreateHttpClient()
private fun recreateHttpClient() = httpClient {
it.followRedirects = false
}
private suspend fun <T> httpClientWithLogin(work: suspend (HttpClient) -> T): T {
return try {
httpClient.login()
work(htpClient)
} catch (e: Exception) {
log.error("Recreating HTTP client", e)
httpClient = recreateHttpClient()
throw e
}
}
suspend fun someApiMethod(): Result = httpClientWithLogin { client ->
...
}
}
I don't particularly like it. For one, I am not sure whether I get multi-threading problems with recreateHttpClient. Also, if a call fails, it is not immediately retried. Can this be handled more elegantly with supervisor coroutine scope? How would you approach this scenario?Dominaezzz
07/29/2019, 9:01 AMDico
07/29/2019, 10:19 PMsuspend fun getHttpClient(): HttpClient
that is implemented with whatever thread safe or local logic to test if a cached client is valid before returning it.