From 7669a94a647f6057bbca02e097fe49818afa2bf5 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 7 Jan 2019 12:12:22 +0100 Subject: [PATCH] Introduce retry on task executor and use it for pagination --- .../room/timeline/TimelineBoundaryCallback.kt | 5 ++-- .../android/internal/task/ConfigurableTask.kt | 9 ++++++ .../android/internal/task/TaskExecutor.kt | 28 +++++++++++++++++-- .../android/internal/util/CoroutineRetry.kt | 24 ---------------- 4 files changed, 38 insertions(+), 28 deletions(-) delete mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/CoroutineRetry.kt diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt index 3c9cb1bbb6..ba57438646 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt @@ -4,10 +4,10 @@ import android.arch.paging.PagedList import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.events.model.EnrichedEvent -import im.vector.matrix.android.internal.task.TaskExecutor -import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.database.model.ChunkEntity import im.vector.matrix.android.internal.database.query.findAllIncludingEvents +import im.vector.matrix.android.internal.task.TaskExecutor +import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.util.PagingRequestHelper import java.util.* @@ -53,6 +53,7 @@ internal class TimelineBoundaryCallback(private val roomId: String, limit = limit) paginationTask.configureWith(params) + .enableRetry() .dispatchTo(object : MatrixCallback { override fun onSuccess(data: TokenChunkEvent) { requestCallback.recordSuccess() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/ConfigurableTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/ConfigurableTask.kt index e5cc7b332f..faf2fb3af3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/ConfigurableTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/ConfigurableTask.kt @@ -13,6 +13,7 @@ internal data class ConfigurableTask( val params: PARAMS, val callbackThread: TaskThread = TaskThread.MAIN, val executionThread: TaskThread = TaskThread.IO, + val retryCount: Int = 0, val callback: MatrixCallback = object : MatrixCallback {} ) : Task { @@ -33,10 +34,18 @@ internal data class ConfigurableTask( return copy(callback = matrixCallback) } + fun enableRetry(retryCount: Int = Int.MAX_VALUE): ConfigurableTask { + return copy(retryCount = retryCount) + } + fun executeBy(taskExecutor: TaskExecutor): Cancelable { return taskExecutor.execute(this) } + override fun toString(): String { + return task.javaClass.name + } + } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt index fce0cd7921..67354642de 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/task/TaskExecutor.kt @@ -1,9 +1,11 @@ package im.vector.matrix.android.internal.task +import arrow.core.Try import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.internal.util.CancelableCoroutine import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import timber.log.Timber @@ -15,14 +17,36 @@ internal class TaskExecutor(private val coroutineDispatchers: MatrixCoroutineDis val job = GlobalScope.launch(task.callbackThread.toDispatcher()) { val resultOrFailure = withContext(task.executionThread.toDispatcher()) { - Timber.v("Executing ${task.javaClass} on ${Thread.currentThread().name}") - task.execute(task.params) + Timber.v("Executing $task on ${Thread.currentThread().name}") + retry(task.retryCount) { + task.execute(task.params) + } } resultOrFailure.fold({ task.callback.onFailure(it) }, { task.callback.onSuccess(it) }) } return CancelableCoroutine(job) } + private suspend fun retry( + times: Int = Int.MAX_VALUE, + initialDelay: Long = 100, // 0.1 second + maxDelay: Long = 10_000, // 10 second + factor: Double = 2.0, + block: suspend () -> Try): Try { + + var currentDelay = initialDelay + repeat(times - 1) { + val blockResult = block() + if (blockResult.isSuccess()) { + return blockResult + } else { + delay(currentDelay) + currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay) + } + } + return block() + } + private fun TaskThread.toDispatcher() = when (this) { TaskThread.MAIN -> coroutineDispatchers.main TaskThread.COMPUTATION -> coroutineDispatchers.computation diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/CoroutineRetry.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/CoroutineRetry.kt deleted file mode 100644 index 28520a69d5..0000000000 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/CoroutineRetry.kt +++ /dev/null @@ -1,24 +0,0 @@ -package im.vector.matrix.android.internal.util - -import arrow.core.Try -import kotlinx.coroutines.delay - -suspend fun retry( - times: Int = Int.MAX_VALUE, - initialDelay: Long = 100, // 0.1 second - maxDelay: Long = 10_000, // 10 second - factor: Double = 2.0, - block: suspend () -> Try): Try { - - var currentDelay = initialDelay - repeat(times - 1) { - val blockResult = block() - if (blockResult.isSuccess()) { - return blockResult - } else { - delay(currentDelay) - currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay) - } - } - return block() -} \ No newline at end of file