kotlinx.coroutines icon indicating copy to clipboard operation
kotlinx.coroutines copied to clipboard

Transaction like behaviour in coroutines to prevent inconsistent data via NonCancellable blocks

Open Burtan opened this issue 3 years ago • 1 comments
trafficstars

Hi, sometimes you want to have code blocks, that should run in total and not get cancelled in between, e.g. when you call an api and you prefer to handle the result.

scope.launch {
    val result = api.purchase(request) // suspending function
    handleResult(result) // suspending function
}

In Android you would most likely tie this function to a ViewModelScope. Now let us assume the user navigates up when the api request is sent and suspending for the result. The result will not get handled and the app might be in an inconsistent state. You could now repair that state later, but you want to reduce the number of times it happens.

Is it now recommended to use a NonCancellable block:

scope.launch {
    withContext(NonCancellable) {
        val result = api.purchase(request) // suspending function
        handleResult(result) // suspending function
    }
}

or to use a longer living scope, like an AppScope? I'd prefer the former, but in the docs NonCancellable is described to be needed rarely and I don't think this situation is rare.

Thanks!

Burtan avatar Jun 30 '22 09:06 Burtan

In Android you would most likely tie this function to a ViewModelScope.

Why? The semantics of a ViewModelScope is exactly that of computations tied to a particular ViewModel, and the idea behind cancellations is to be able to throw away the computations once they become irrelevant.

use a longer living scope, like an AppScope

Sounds like the proper solution, yes.

dkhalanskyjb avatar Jun 30 '22 12:06 dkhalanskyjb