mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 12:07:28 +00:00
Do not automatically restart the sync in case it is Terminated.
Also simplify the computation of the backoff delay.
This commit is contained in:
committed by
Benoit Marty
parent
b28b2ceeed
commit
25505d6e8a
@@ -138,7 +138,7 @@ class SyncOrchestrator(
|
||||
SyncStateAction.StopSync
|
||||
} else if (syncState == SyncState.Idle && isAppActive && isNetworkAvailable) {
|
||||
SyncStateAction.StartSync
|
||||
} else if (syncState.isDead() && isAppActive && isNetworkAvailable) {
|
||||
} else if (syncState == SyncState.Error && isAppActive && isNetworkAvailable) {
|
||||
// The sync service has given up, for instance because the homeserver has expired our sliding sync
|
||||
// session and answered 400 M_UNKNOWN_POS. Nothing else will ever restart it, so do it from here,
|
||||
// else the application is stuck until its data is cleared.
|
||||
@@ -184,8 +184,18 @@ class SyncOrchestrator(
|
||||
@VisibleForTesting
|
||||
internal val FIRST_RESTART_DELAY = 1.seconds
|
||||
|
||||
/**
|
||||
* Exponential backoff, from [FIRST_RESTART_DELAY], doubling on every attempt, up to [FIRST_RESTART_DELAY * 32].
|
||||
*/
|
||||
@VisibleForTesting
|
||||
internal val MAX_RESTART_DELAY = 30.seconds
|
||||
internal val RESTART_BACKOFF_DELAYS = listOf(
|
||||
FIRST_RESTART_DELAY,
|
||||
FIRST_RESTART_DELAY * 2,
|
||||
FIRST_RESTART_DELAY * 4,
|
||||
FIRST_RESTART_DELAY * 8,
|
||||
FIRST_RESTART_DELAY * 16,
|
||||
FIRST_RESTART_DELAY * 32,
|
||||
)
|
||||
|
||||
/**
|
||||
* Duration during which the sync service has to stay running before the restart backoff is reset.
|
||||
@@ -193,17 +203,8 @@ internal val MAX_RESTART_DELAY = 30.seconds
|
||||
@VisibleForTesting
|
||||
internal val RESTART_BACKOFF_RESET_DELAY = 30.seconds
|
||||
|
||||
/**
|
||||
* Return true if the sync service has stopped and will not restart by itself.
|
||||
*/
|
||||
private fun SyncState.isDead() = this == SyncState.Error || this == SyncState.Terminated
|
||||
|
||||
/**
|
||||
* Exponential backoff, from [FIRST_RESTART_DELAY], doubling on every attempt, up to [MAX_RESTART_DELAY].
|
||||
*/
|
||||
private fun restartDelay(attempt: Int): Duration {
|
||||
val exponent = attempt.coerceIn(0, 5)
|
||||
return (FIRST_RESTART_DELAY * (1 shl exponent)).coerceAtMost(MAX_RESTART_DELAY)
|
||||
return RESTART_BACKOFF_DELAYS[attempt.coerceIn(0, RESTART_BACKOFF_DELAYS.lastIndex)]
|
||||
}
|
||||
|
||||
private enum class SyncStateAction {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
package io.element.android.appnav
|
||||
|
||||
import io.element.android.appnav.session.FIRST_RESTART_DELAY
|
||||
import io.element.android.appnav.session.MAX_RESTART_DELAY
|
||||
import io.element.android.appnav.session.RESTART_BACKOFF_DELAYS
|
||||
import io.element.android.appnav.session.RESTART_BACKOFF_RESET_DELAY
|
||||
import io.element.android.appnav.session.SyncOrchestrator
|
||||
import io.element.android.features.networkmonitor.api.NetworkStatus
|
||||
@@ -441,25 +441,6 @@ class SyncOrchestratorTest {
|
||||
startSyncRecorder.assertions().isCalledOnce()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when the sync service is terminated, it will be restarted after a delay`() = runTest {
|
||||
val startSyncRecorder = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
|
||||
val syncService = FakeSyncService(initialSyncState = SyncState.Terminated).apply {
|
||||
startSyncLambda = startSyncRecorder
|
||||
}
|
||||
val syncOrchestrator = createSyncOrchestrator(
|
||||
matrixClient = FakeMatrixClient(syncService = syncService),
|
||||
networkMonitor = FakeNetworkMonitor(initialStatus = NetworkStatus.Connected),
|
||||
appForegroundStateService = FakeAppForegroundStateService(initialForegroundValue = true),
|
||||
)
|
||||
|
||||
// We start observing
|
||||
syncOrchestrator.observeStates()
|
||||
|
||||
advanceTimeBy(FIRST_RESTART_DELAY * 2)
|
||||
startSyncRecorder.assertions().isCalledOnce()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when the sync service keeps dying, the delay between the restarts increases`() = runTest {
|
||||
val startSyncRecorder = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
|
||||
@@ -538,7 +519,7 @@ class SyncOrchestratorTest {
|
||||
// We start observing
|
||||
syncOrchestrator.observeStates()
|
||||
|
||||
advanceTimeBy(MAX_RESTART_DELAY * 2)
|
||||
advanceTimeBy(RESTART_BACKOFF_DELAYS.last() * 2)
|
||||
startSyncRecorder.assertions().isNeverCalled()
|
||||
}
|
||||
|
||||
@@ -557,7 +538,7 @@ class SyncOrchestratorTest {
|
||||
// We start observing
|
||||
syncOrchestrator.observeStates()
|
||||
|
||||
advanceTimeBy(MAX_RESTART_DELAY * 2)
|
||||
advanceTimeBy(RESTART_BACKOFF_DELAYS.last() * 2)
|
||||
startSyncRecorder.assertions().isNeverCalled()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user