Stylianos Gakis
01/20/2022, 11:27 AMStylianos Gakis
01/20/2022, 11:27 AMsealed class QueryResult<out T> {
data class Success<T>(val data: T) : QueryResult<T>()
sealed class Error : QueryResult<Nothing>() {
data class NoDataError() : Error()
data class GeneralError() : Error()
data class QueryError() : Error()
data class NetworkError() : Error()
}
... toOption(), toEither, etc convenience functions to turn into arrow.core types
}
fun <T> Response<T>.toQueryResult(): QueryResult<T> {
val data = data
return when {
hasErrors() -> QueryResult.Error.QueryError()
data != null -> QueryResult.Success(data)
else -> QueryResult.Error.NoDataError()
}
}
suspend fun <T> ApolloCall<T>.safeQuery(): QueryResult<T> {
return try {
await().toQueryResult()
} catch (apolloException: ApolloException) {
QueryResult.Error.NetworkError()
} catch (throwable: Throwable) {
QueryResult.Error.GeneralError()
}
}
But my question then comes, am I breaking cancellation handling this way? I can see that .await()
is a suspendCancellableCoroutine
, but I am then wrapping it in a try which catches CancellationException
too, since I am catching Throwable
.
Would this function in this way if the scope gets cancelled:
1. The flow/await cancels, and the query is stopped properly
2. The CancellationException is caught by my function
3. If anything is called under await() it does continue normally even though we were cancelled since I âswallowedâ the exception there. (What I am trying to avoid)
4. On the next cancellation cooperating function we will actually exit since the job is in âcancellingâ state. (Does this step actually happen? Or does the exception get swallowed completely which is even worse?)
And would maybe something like adding this in both functions this fix this problem? (Or perhaps in a different order of catching if itâd matter?)
try {
await().toQueryResult()
} catch (apolloException: ApolloException) {
QueryResult.Error.NetworkError(apolloException.localizedMessage)
} catch(cancelationException: CancelationException) {
throw cancelationException
} catch (throwable: Throwable) {
QueryResult.Error.GeneralError(throwable.localizedMessage)
}
Or am I just tripping and none of this happens? Ugh cancellation in Coroutines sometimes feels so tricky, every time I think I get it, I realize I donât đ
Sorry for asking such a big question, the thing is I find it very hard to setup a test for all these scenarios with my limited coroutines understanding while involving apollo-kotlin too. Iâd rather ask if someone knows before I spend way too much time trying to understand it and potentially fail.wasyl
01/20/2022, 11:31 AMBut my question then comes, am I breaking cancellation handling this way?Probably yes, or if not cancellation then structured concurrency in some way. Even with Kotlinâs own
runCatching
you should always rethrow CancellationException
(https://github.com/Kotlin/kotlinx.coroutines/issues/1814)Stylianos Gakis
01/20/2022, 11:34 AMCancellationException
be the fix? The linked issue seems to point to âyesâ right?bod
01/20/2022, 12:53 PMStylianos Gakis
01/20/2022, 1:00 PMwasyl
01/20/2022, 1:45 PMephemient
01/20/2022, 6:01 PM