Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Differentiate unauthenticated errors from other errors in safeFlow() #2320

Merged
merged 1 commit into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,22 @@ sealed interface ApolloOperationError {
}
}

data class OperationError(private val message: String) : ApolloOperationError {
override val throwable: Throwable? = null
sealed interface OperationError : ApolloOperationError {
object Unathenticated : OperationError {
override val throwable: Throwable? = null

override fun toString(): String {
return "OperationError.Unathenticated"
}
}

data class Other(private val message: String) : OperationError {
override val throwable: Throwable? = null

override fun toString(): String {
return "OperationError.Other(message=$message)"
}
}
}
}

Expand Down Expand Up @@ -103,6 +117,17 @@ fun ErrorMessage(apolloOperationError: ApolloOperationError): ErrorMessage = obj
}
}

@JvmInline
value class ExtensionErrorType(val value: String) {
companion object {
val Unauthenticated = ExtensionErrorType("UNAUTHENTICATED")
}
}

fun Error.extensionErrorType(): ExtensionErrorType? {
return extensions?.get("errorType")?.let { ExtensionErrorType(it.toString()) }
}

// https://www.apollographql.com/docs/kotlin/essentials/errors/#truth-table
private fun <D : Operation.Data> IorRaise<Nel<ApolloOperationError>>.parseResponse(response: ApolloResponse<D>): D {
val exception = response.exception
Expand All @@ -129,14 +154,18 @@ private fun <D : Operation.Data> IorRaise<Nel<ApolloOperationError>>.parseRespon
private fun List<Error>?.mapToOperationErrors(): Nel<ApolloOperationError>? {
if (this == null) return null
return map { error ->
ApolloOperationError.OperationError(
buildString {
append(error.message)
if (error.extensions != null) {
append(error.extensions!!.toList().joinToString(prefix = " ext: [", postfix = "]", separator = ", "))
}
},
)
if (error.extensionErrorType() == ExtensionErrorType.Unauthenticated) {
ApolloOperationError.OperationError.Unathenticated
} else {
ApolloOperationError.OperationError.Other(
buildString {
append(error.message)
if (error.extensions != null) {
append(error.extensions!!.toList().joinToString(prefix = " ext: [", postfix = "]", separator = ", "))
}
},
)
}
}.toNonEmptyListOrNull()
}

Expand All @@ -145,7 +174,7 @@ private fun List<Error>?.mapToOperationErrors(): Nel<ApolloOperationError>? {
*/
private fun <D : Operation.Data> IorNel<ApolloOperationError, D>.iorToEither(): Either<ApolloOperationError, D> {
return mapLeft { errors ->
ApolloOperationError.OperationError(
ApolloOperationError.OperationError.Other(
errors.joinToString(prefix = " [", postfix = "]", separator = ", ") { it.toString() },
)
}.toEither()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import com.apollographql.apollo.api.Operation.Data
import com.apollographql.apollo.exception.CacheMissException
import com.apollographql.apollo.interceptor.ApolloInterceptor
import com.apollographql.apollo.interceptor.ApolloInterceptorChain
import com.hedvig.android.apollo.ExtensionErrorType
import com.hedvig.android.apollo.extensionErrorType
import com.hedvig.android.auth.AuthTokenService
import com.hedvig.android.core.tracking.ErrorSource
import com.hedvig.android.core.tracking.logError
Expand Down Expand Up @@ -103,20 +105,13 @@ private data class LoggableGraphqlError(
)

data class Extensions(
val errorType: ErrorType?,
val errorType: ExtensionErrorType?,
val uncategorizedExtensions: Map<String, Any?>?,
) {
@JvmInline
value class ErrorType(val value: String) {
companion object {
val Unauthenticated = ErrorType("UNAUTHENTICATED")
}
}
}
)
}

private fun List<LoggableGraphqlError>.isUnathenticated(): Boolean {
return any { it.extensions.errorType == LoggableGraphqlError.Extensions.ErrorType.Unauthenticated }
return any { it.extensions.errorType == ExtensionErrorType.Unauthenticated }
}

private fun ApolloKotlinError.toGraphqlError(): LoggableGraphqlError {
Expand All @@ -125,7 +120,7 @@ private fun ApolloKotlinError.toGraphqlError(): LoggableGraphqlError {
locations = this.locations?.map { LoggableGraphqlError.Location(it.line, it.column) },
paths = this.path?.map { LoggableGraphqlError.Path(it.toString()) },
extensions = LoggableGraphqlError.Extensions(
errorType = this.extensions?.get("errorType")?.let { LoggableGraphqlError.Extensions.ErrorType(it.toString()) },
errorType = this.extensionErrorType(),
uncategorizedExtensions = this.extensions?.minus("errorType"),
),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class HasAnyActiveConversationUseCase(
either {
val data = result
.onLeft { apolloOperationError ->
if (apolloOperationError is ApolloOperationError.OperationError.Unathenticated) return@onLeft
logcat(LogPriority.ERROR, apolloOperationError.throwable) {
"isEligibleToShowTheChatIcon cant determine if the chat icon should be shown. $apolloOperationError"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ internal class HomePresenterTest {
assertThat(awaitItem()).isEqualTo(HomeUiState.Loading)
assertThat(getHomeDataUseCase.forceNetworkFetchTurbine.awaitItem()).isFalse()

getHomeDataUseCase.responseTurbine.add(ApolloOperationError.OperationError("").left())
getHomeDataUseCase.responseTurbine.add(ApolloOperationError.OperationError.Other("").left())
assertThat(awaitItem()).isInstanceOf<HomeUiState.Error>()

sendEvent(HomeEvent.RefreshData)
assertThat(getHomeDataUseCase.forceNetworkFetchTurbine.awaitItem()).isTrue()
assertThat(awaitItem()).isInstanceOf<HomeUiState.Loading>()

getHomeDataUseCase.responseTurbine.add(ApolloOperationError.OperationError("").left())
getHomeDataUseCase.responseTurbine.add(ApolloOperationError.OperationError.Other("").left())
assertThat(awaitItem()).isInstanceOf<HomeUiState.Error>()
}
}
Expand All @@ -72,7 +72,7 @@ internal class HomePresenterTest {
homePresenter.test(HomeUiState.Loading) {
assertThat(awaitItem()).isEqualTo(HomeUiState.Loading)

getHomeDataUseCase.responseTurbine.add(ApolloOperationError.OperationError("").left())
getHomeDataUseCase.responseTurbine.add(ApolloOperationError.OperationError.Other("").left())
assertThat(awaitItem()).isInstanceOf<HomeUiState.Error>()

sendEvent(HomeEvent.RefreshData)
Expand Down Expand Up @@ -208,7 +208,7 @@ internal class HomePresenterTest {
homePresenter.test(HomeUiState.Loading) {
assertThat(awaitItem()).isEqualTo(HomeUiState.Loading)

getHomeDataUseCase.responseTurbine.add(ApolloOperationError.OperationError("").left())
getHomeDataUseCase.responseTurbine.add(ApolloOperationError.OperationError.Other("").left())
assertThat(awaitItem()).isInstanceOf<HomeUiState.Error>()

getHomeDataUseCase.responseTurbine.add(someIrrelevantHomeDataInstance.right())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class EurobonusPresenterTest {
),
) {
awaitItem()
getEurobonusDataUseCase.responseTurbine.add(ApolloOperationError.OperationError("msg").left())
getEurobonusDataUseCase.responseTurbine.add(ApolloOperationError.OperationError.Other("msg").left())
assertThat(awaitItem()).isEqualTo(
EurobonusUiState(
canSubmit = false,
Expand Down Expand Up @@ -151,7 +151,7 @@ class EurobonusPresenterTest {
awaitItem()
sendEvent(EurobonusEvent.SubmitEditedEurobonus)
awaitItem()
updateEurobonusNumberUseCase.responseTurbine.add(ApolloOperationError.OperationError("msg").left())
updateEurobonusNumberUseCase.responseTurbine.add(ApolloOperationError.OperationError.Other("msg").left())
assertThat(awaitItem().hasError).isEqualTo(true)
}
}
Expand Down
Loading