impl ui logic
This commit is contained in:
@@ -45,11 +45,11 @@ dependencies {
|
||||
api(libs.okhttp)
|
||||
|
||||
implementation(libs.okhttp.logging)
|
||||
implementation(libs.converter.gson)
|
||||
implementation(libs.retrofit.gson)
|
||||
|
||||
api(libs.moshi)
|
||||
api(libs.moshiKotlin)
|
||||
api(libs.retrofitMoshi)
|
||||
api(libs.moshi.kotlin)
|
||||
api(libs.retrofit.moshi)
|
||||
|
||||
implementation(projects.core.common)
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package ru.fincode.tsudesk.core.network.interceptor
|
||||
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
import java.io.IOException
|
||||
import kotlin.math.min
|
||||
|
||||
|
||||
class RetryInterceptor(
|
||||
private val maxAttempts: Int = 3,
|
||||
private val baseDelayMs: Long = 300L
|
||||
) : Interceptor {
|
||||
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
val request = chain.request()
|
||||
|
||||
// На всякий: ретраим только идемпотентные методы
|
||||
val method = request.method.uppercase()
|
||||
val retryAllowed = method == "GET" || method == "HEAD"
|
||||
|
||||
var attempt = 1
|
||||
var lastException: IOException? = null
|
||||
var lastResponse: Response? = null
|
||||
|
||||
while (attempt <= maxAttempts) {
|
||||
// закрываем предыдущий response, чтобы не текли ресурсы
|
||||
lastResponse?.close()
|
||||
lastResponse = null
|
||||
|
||||
try {
|
||||
val response = chain.proceed(request)
|
||||
|
||||
if (!retryAllowed) return response
|
||||
|
||||
if (!response.shouldRetry()) {
|
||||
return response
|
||||
}
|
||||
|
||||
// Нужно ретраить — подождём и попробуем снова
|
||||
if (attempt == maxAttempts) return response
|
||||
|
||||
sleepBackoff(attempt)
|
||||
|
||||
attempt++
|
||||
continue
|
||||
} catch (e: IOException) {
|
||||
lastException = e
|
||||
if (!retryAllowed || attempt == maxAttempts) throw e
|
||||
|
||||
sleepBackoff(attempt)
|
||||
|
||||
attempt++
|
||||
}
|
||||
}
|
||||
|
||||
// Теоретически не должны попасть сюда
|
||||
lastResponse?.let { return it }
|
||||
lastException?.let { throw it }
|
||||
throw IOException("RetryInterceptor: exhausted attempts without response/exception")
|
||||
}
|
||||
|
||||
private fun Response.shouldRetry(): Boolean {
|
||||
return when (code) {
|
||||
408, 429 -> true
|
||||
in 500..599 -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun sleepBackoff(attempt: Int) {
|
||||
val delay = baseDelayMs * min(attempt.toLong(), 2L)
|
||||
try {
|
||||
Thread.sleep(delay)
|
||||
} catch (_: InterruptedException) {
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user