From dde3ed7ee7278203fde969c0e0c9103efa29947a Mon Sep 17 00:00:00 2001 From: stylianosgakis Date: Mon, 26 Aug 2024 13:05:25 +0200 Subject: [PATCH] Stop relying on isLast After feedback by Martin here https://github.com/apollographql/apollo-kotlin/issues/6129 Replace the implementation which relied on the isLast to a much more robust implementation which should cover what the previous implementation did plus more. --- .../hedvig/android/apollo/ApolloCallExt.kt | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/app/apollo/apollo-core/src/main/kotlin/com/hedvig/android/apollo/ApolloCallExt.kt b/app/apollo/apollo-core/src/main/kotlin/com/hedvig/android/apollo/ApolloCallExt.kt index 24c878f50f..e5d37e5233 100644 --- a/app/apollo/apollo-core/src/main/kotlin/com/hedvig/android/apollo/ApolloCallExt.kt +++ b/app/apollo/apollo-core/src/main/kotlin/com/hedvig/android/apollo/ApolloCallExt.kt @@ -14,10 +14,8 @@ import com.hedvig.android.apollo.ApolloOperationError.CacheMiss import com.hedvig.android.apollo.ApolloOperationError.OperationError import com.hedvig.android.apollo.ApolloOperationError.OperationException import com.hedvig.android.core.common.ErrorMessage -import com.hedvig.android.logger.LogPriority -import com.hedvig.android.logger.logcat import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.filterNot +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map sealed interface ApolloOperationError { @@ -51,19 +49,25 @@ suspend fun ApolloCall.safeExecute( } fun ApolloCall.safeFlow(): Flow> { - return toFlow() - .filterNot { response -> - val isTemporaryCacheMiss = !response.isLast && response.exception is CacheMissException - // If we get a cache miss, but we know that we are awaiting a new response after that anyway, we do not need to - // emit the cache miss at all. We can just wait for the next response to come instead. - if (isTemporaryCacheMiss) { - logcat(LogPriority.DEBUG) { - "Apollo call:${this.operation.name()} emitted a cache miss, but another response is coming" - } + return flow> { + var hasEmitted = false + var errorResponse: ApolloResponse? = null + toFlow().collect { + if (it.exception != null) { + // Some errors may be followed by valid responses. + // In that case, wait for the next response to come instead. + errorResponse = it + } else { + hasEmitted = true + emit(it) } - isTemporaryCacheMiss } - .map { either { parseResponse(it) } } + val errorResponseValue = errorResponse + if (!hasEmitted && errorResponseValue != null) { + // Flow has terminated without a valid response, emit the error one if it exists. + emit(errorResponseValue) + } + }.map { either { parseResponse(it) } } } fun ApolloCall.safeFlow(