Better handling on 429

This commit is contained in:
Benoit Marty 2021-04-01 13:51:16 +02:00
parent 1f2d6bea21
commit 0bc864fc37
3 changed files with 18 additions and 4 deletions

View File

@ -37,6 +37,18 @@ fun Throwable.shouldBeRetried(): Boolean {
|| (this is Failure.ServerError && error.code == MatrixError.M_LIMIT_EXCEEDED)
}
/**
* Get the retry delay in case of rate limit exceeded error, adding 100 ms, of defaultValue otherwise
*/
fun Throwable.getRetryDelay(defaultValue: Long): Long {
return (this as? Failure.ServerError)
?.error
?.takeIf { it.code == MatrixError.M_LIMIT_EXCEEDED }
?.retryAfterMillis
?.plus(100L)
?: defaultValue
}
fun Throwable.isInvalidPassword(): Boolean {
return this is Failure.ServerError
&& error.code == MatrixError.M_FORBIDDEN

View File

@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.network
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.delay
import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.failure.getRetryDelay
import org.matrix.android.sdk.api.failure.shouldBeRetried
import org.matrix.android.sdk.internal.network.ssl.CertUtil
import retrofit2.HttpException
@ -68,8 +69,9 @@ internal suspend inline fun <DATA> executeRequest(globalErrorReceiver: GlobalErr
?.also { unrecognizedCertificateException -> throw unrecognizedCertificateException }
if (canRetry && currentRetryCount++ < maxRetriesCount && exception.shouldBeRetried()) {
delay(currentDelay)
currentDelay = (currentDelay * 2L).coerceAtMost(maxDelayBeforeRetry)
// In case of 429, ensure we wait enough
delay(currentDelay.coerceAtLeast(exception.getRetryDelay(0)))
currentDelay = currentDelay.times(2L).coerceAtMost(maxDelayBeforeRetry)
// Try again (loop)
} else {
throw when (exception) {

View File

@ -24,6 +24,7 @@ import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.auth.data.SessionParams
import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.failure.MatrixError
import org.matrix.android.sdk.api.failure.getRetryDelay
import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.util.Cancelable
@ -148,8 +149,7 @@ internal class EventSenderProcessorCoroutine @Inject constructor(
task.markAsFailedOrRetry(exception, 0)
}
(exception is Failure.ServerError && exception.error.code == MatrixError.M_LIMIT_EXCEEDED) -> {
val delay = exception.error.retryAfterMillis?.plus(100) ?: 3_000
task.markAsFailedOrRetry(exception, delay)
task.markAsFailedOrRetry(exception, exception.getRetryDelay(3_000))
}
exception is CancellationException -> {
Timber.v("## $task has been cancelled, try next task")