Cancel sync request on pause and timeout to 0 after pause (#404)

This commit is contained in:
Benoit Marty 2019-08-08 16:03:11 +02:00
parent 9d5433a857
commit eaf6a9923a
2 changed files with 33 additions and 18 deletions

View File

@ -12,6 +12,7 @@ Improvements:
- Enable proper cancellation of suspending functions (including db transaction) - Enable proper cancellation of suspending functions (including db transaction)
- Enhances network connectivity checks in SDK - Enhances network connectivity checks in SDK
- Add "View Edit History" item in the message bottom sheet (#401) - Add "View Edit History" item in the message bottom sheet (#401)
- Cancel sync request on pause and timeout to 0 after pause (#404)


Other changes: Other changes:
- Show sync progress also in room detail screen (#403) - Show sync progress also in room detail screen (#403)

View File

@ -30,6 +30,7 @@ import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.TaskThread import im.vector.matrix.android.internal.task.TaskThread
import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
import kotlinx.coroutines.CancellationException
import timber.log.Timber import timber.log.Timber
import java.net.SocketTimeoutException import java.net.SocketTimeoutException
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
@ -70,6 +71,8 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
if (state is SyncState.RUNNING) { if (state is SyncState.RUNNING) {
Timber.v("Pause sync...") Timber.v("Pause sync...")
updateStateTo(SyncState.PAUSED) updateStateTo(SyncState.PAUSED)
cancelableTask?.cancel()
lock.notify()
} }
} }


@ -90,18 +93,25 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
backgroundDetectionObserver.register(this) backgroundDetectionObserver.register(this)


while (state != SyncState.KILLING) { while (state != SyncState.KILLING) {
Timber.v("Entering loop, state: $state")

if (!networkConnectivityChecker.isConnected() || state == SyncState.PAUSED) { if (!networkConnectivityChecker.isConnected() || state == SyncState.PAUSED) {
Timber.v("Sync is Paused. Waiting...") Timber.v("No network or sync is Paused. Waiting...")
synchronized(lock) { synchronized(lock) {
lock.wait() lock.wait()
} }
Timber.v("...unlocked")
} else { } else {
if (state !is SyncState.RUNNING) { if (state !is SyncState.RUNNING) {
updateStateTo(SyncState.RUNNING(afterPause = true)) updateStateTo(SyncState.RUNNING(afterPause = true))
} }
Timber.v("[$this] Execute sync request with timeout $DEFAULT_LONG_POOL_TIMEOUT")
// No timeout after a pause
val timeout = state.let { if (it is SyncState.RUNNING && it.afterPause) 0 else DEFAULT_LONG_POOL_TIMEOUT }

Timber.v("Execute sync request with timeout $timeout")
val latch = CountDownLatch(1) val latch = CountDownLatch(1)
val params = SyncTask.Params(DEFAULT_LONG_POOL_TIMEOUT) val params = SyncTask.Params(timeout)


cancelableTask = syncTask.configureWith(params) { cancelableTask = syncTask.configureWith(params) {
this.callbackThread = TaskThread.SYNC this.callbackThread = TaskThread.SYNC
@ -109,29 +119,31 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
this.callback = object : MatrixCallback<Unit> { this.callback = object : MatrixCallback<Unit> {


override fun onSuccess(data: Unit) { override fun onSuccess(data: Unit) {
Timber.v("onSuccess")
latch.countDown() latch.countDown()
} }


override fun onFailure(failure: Throwable) { override fun onFailure(failure: Throwable) {
if (failure is Failure.NetworkConnection if (failure is Failure.NetworkConnection && failure.cause is SocketTimeoutException) {
&& failure.cause is SocketTimeoutException) {
// Timeout are not critical // Timeout are not critical
Timber.v("Timeout") Timber.v("Timeout")
} else { } else if (failure is Failure.Unknown && failure.throwable is CancellationException) {
Timber.e(failure) Timber.v("Cancelled")
} } else if (failure is Failure.ServerError

if (failure !is Failure.NetworkConnection
|| failure.cause is JsonEncodingException) {
// Wait 10s before retrying
sleep(RETRY_WAIT_TIME_MS)
}

if (failure is Failure.ServerError
&& (failure.error.code == MatrixError.UNKNOWN_TOKEN || failure.error.code == MatrixError.MISSING_TOKEN)) { && (failure.error.code == MatrixError.UNKNOWN_TOKEN || failure.error.code == MatrixError.MISSING_TOKEN)) {
// No token or invalid token, stop the thread // No token or invalid token, stop the thread
Timber.w(failure)
updateStateTo(SyncState.KILLING) updateStateTo(SyncState.KILLING)
} else {
Timber.e(failure)

if (failure !is Failure.NetworkConnection || failure.cause is JsonEncodingException) {
// Wait 10s before retrying
Timber.v("Wait 10s")
sleep(RETRY_WAIT_TIME_MS)
} }
}

latch.countDown() latch.countDown()
} }
} }
@ -139,9 +151,11 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
.executeBy(taskExecutor) .executeBy(taskExecutor)


latch.await() latch.await()
if (state is SyncState.RUNNING) { state.let {
if (it is SyncState.RUNNING && it.afterPause) {
updateStateTo(SyncState.RUNNING(afterPause = false)) updateStateTo(SyncState.RUNNING(afterPause = false))
} }
}


Timber.v("...Continue") Timber.v("...Continue")
} }