Update state in runUpdatingState when CancellationException occurs (#5243)
This commit is contained in:
@@ -10,6 +10,7 @@ package io.element.android.libraries.architecture
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.Stable
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
@@ -159,16 +160,19 @@ suspend inline fun <T> runUpdatingState(
|
||||
callsInPlace(resultBlock, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
state.value = AsyncAction.Loading
|
||||
return resultBlock().fold(
|
||||
return try {
|
||||
resultBlock()
|
||||
} catch (e: TimeoutCancellationException) {
|
||||
state.value = AsyncAction.Failure(errorTransform(e))
|
||||
throw e
|
||||
}.fold(
|
||||
onSuccess = {
|
||||
state.value = AsyncAction.Success(it)
|
||||
Result.success(it)
|
||||
},
|
||||
onFailure = {
|
||||
val error = errorTransform(it)
|
||||
state.value = AsyncAction.Failure(
|
||||
error = error,
|
||||
)
|
||||
state.value = AsyncAction.Failure(error)
|
||||
Result.failure(error)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.architecture
|
||||
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import org.junit.Assert.assertSame
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Assert.fail
|
||||
import org.junit.Test
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
class AsyncActionTest {
|
||||
@Test
|
||||
fun `updates state on timeout`() = runTest {
|
||||
val state: MutableState<AsyncAction<Int>> = mutableStateOf(AsyncAction.Uninitialized)
|
||||
val timeoutMillis = 500L
|
||||
val operationTimeMillis = 1000L
|
||||
|
||||
try {
|
||||
runUpdatingState(state = state) {
|
||||
withTimeout(timeoutMillis.milliseconds) {
|
||||
delay(operationTimeMillis)
|
||||
}
|
||||
Result.success(0)
|
||||
}
|
||||
fail("Expected TimeoutCancellationException, but nothing was thrown")
|
||||
} catch (e: TimeoutCancellationException) {
|
||||
assertTrue(state.value.isFailure())
|
||||
assertSame(e, state.value.errorOrNull())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,6 @@ import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.room.ForwardEventException
|
||||
import io.element.android.libraries.matrix.impl.roomlist.roomOrNull
|
||||
import io.element.android.libraries.matrix.impl.timeline.runWithTimelineListenerRegistered
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import org.matrix.rustcomponents.sdk.MsgLikeKind
|
||||
import org.matrix.rustcomponents.sdk.RoomListService
|
||||
@@ -63,9 +62,6 @@ class RoomContentForwarder(
|
||||
}
|
||||
}.onFailure {
|
||||
failedForwardingTo.add(RoomId(room.id()))
|
||||
if (it is CancellationException) {
|
||||
throw it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user