diff --git a/Confidence/src/main/java/com/spotify/confidence/Confidence.kt b/Confidence/src/main/java/com/spotify/confidence/Confidence.kt index c55d91b0..431be4c4 100644 --- a/Confidence/src/main/java/com/spotify/confidence/Confidence.kt +++ b/Confidence/src/main/java/com/spotify/confidence/Confidence.kt @@ -1,6 +1,7 @@ package com.spotify.confidence import android.content.Context +import com.spotify.confidence.ConfidenceError.HttpError import com.spotify.confidence.ConfidenceError.ParseError import com.spotify.confidence.apply.FlagApplierWithRetries import com.spotify.confidence.cache.DiskStorage @@ -287,6 +288,8 @@ class Confidence internal constructor( } } catch (e: ParseError) { throw ParseError(e.message) + } catch (e: HttpError) { + throw e } } diff --git a/Confidence/src/main/java/com/spotify/confidence/ConfidenceError.kt b/Confidence/src/main/java/com/spotify/confidence/ConfidenceError.kt index 9f75b507..f77b8f8a 100644 --- a/Confidence/src/main/java/com/spotify/confidence/ConfidenceError.kt +++ b/Confidence/src/main/java/com/spotify/confidence/ConfidenceError.kt @@ -22,5 +22,10 @@ class ConfidenceError { val flag: String ) : Error(message) + data class HttpError( + val httpCode: Int, + override val message: String + ) : Error(message) + class InvalidContextInMessage : Error("Field 'context' is not allowed in event's data") } diff --git a/Confidence/src/main/java/com/spotify/confidence/EventSenderUploader.kt b/Confidence/src/main/java/com/spotify/confidence/EventSenderUploader.kt index 9bdb24a1..29f653b5 100644 --- a/Confidence/src/main/java/com/spotify/confidence/EventSenderUploader.kt +++ b/Confidence/src/main/java/com/spotify/confidence/EventSenderUploader.kt @@ -65,19 +65,20 @@ internal class EventSenderUploaderImpl( .post(networkJson.encodeToString(events).toRequestBody()) .build() - val response = httpClient.newCall(httpRequest).await() - if (!response.isSuccessful) { - debugLogger?.logError(message = "Failed to upload events. http code ${response.code}") - } - when (response.code) { - // clean up in case of success - 200 -> true - // we shouldn't cleanup for rate limiting - // TODO("return retry-after") - 429 -> false - // if batch couldn't be processed, we should clean it up - in 400..499 -> true - else -> false + httpClient.newCall(httpRequest).await().use { response -> + if (!response.isSuccessful) { + debugLogger?.logError(message = "Failed to upload events. http code ${response.code}") + } + when (response.code) { + // clean up in case of success + 200 -> true + // we shouldn't cleanup for rate limiting + // TODO("return retry-after") + 429 -> false + // if batch couldn't be processed, we should clean it up + in 400..499 -> true + else -> false + } } } diff --git a/Confidence/src/main/java/com/spotify/confidence/RemoteFlagResolver.kt b/Confidence/src/main/java/com/spotify/confidence/RemoteFlagResolver.kt index f9f9e404..b4e2d9dd 100644 --- a/Confidence/src/main/java/com/spotify/confidence/RemoteFlagResolver.kt +++ b/Confidence/src/main/java/com/spotify/confidence/RemoteFlagResolver.kt @@ -57,8 +57,7 @@ internal class RemoteFlagResolver( val startTime = System.nanoTime() var status = Telemetry.RequestStatus.SUCCESS try { - val result = httpClient.newCall(httpRequest).await() - result.toResolveFlags() + httpClient.newCall(httpRequest).await().use { it.toResolveFlags() } } catch (e: SocketTimeoutException) { status = Telemetry.RequestStatus.TIMEOUT throw e @@ -92,22 +91,16 @@ internal class RemoteFlagResolver( private fun Response.toResolveFlags(): ResolveResponse { if (!isSuccessful) { debugLogger?.logError("Failed to resolve flags. Http code: $code") + throw ConfidenceError.HttpError(code, "Failed to resolve flags. Http code: $code") } - body?.let { body -> - val bodyString = body.string() - - // building the json class responsible for serializing the object - val networkJson = Json { - serializersModule = SerializersModule { - ignoreUnknownKeys = true - } + val bodyString = body?.string() + ?: throw ConfidenceError.ParseError("Response body is null", listOf()) + val networkJson = Json { + serializersModule = SerializersModule { + ignoreUnknownKeys = true } - try { - return ResolveResponse.Resolved(networkJson.decodeFromString(bodyString)) - } finally { - body.close() - } - } ?: throw ConfidenceError.ParseError("Response body is null", listOf()) + } + return ResolveResponse.Resolved(networkJson.decodeFromString(bodyString)) } } diff --git a/Confidence/src/main/java/com/spotify/confidence/client/FlagApplierClientImpl.kt b/Confidence/src/main/java/com/spotify/confidence/client/FlagApplierClientImpl.kt index 0af66ae3..e67d6cd6 100644 --- a/Confidence/src/main/java/com/spotify/confidence/client/FlagApplierClientImpl.kt +++ b/Confidence/src/main/java/com/spotify/confidence/client/FlagApplierClientImpl.kt @@ -94,16 +94,16 @@ internal class FlagApplierClientImpl : FlagApplierClient { extraHeaders[Telemetry.HEADER_NAME] = headerValue } - val result = applyInteractor.invoke(request, extraHeaders).runCatching { - if (isSuccessful) { - Result.Success(Unit) - } else { - Result.Failure() + return try { + applyInteractor.invoke(request, extraHeaders).use { response -> + if (response.isSuccessful) { + Result.Success(Unit) + } else { + Result.Failure() + } } - }.getOrElse { + } catch (_: Exception) { Result.Failure() } - - return result } } diff --git a/Provider/src/main/java/com/spotify/confidence/openfeature/ConfidenceFeatureProvider.kt b/Provider/src/main/java/com/spotify/confidence/openfeature/ConfidenceFeatureProvider.kt index d7c48bac..73d2438f 100644 --- a/Provider/src/main/java/com/spotify/confidence/openfeature/ConfidenceFeatureProvider.kt +++ b/Provider/src/main/java/com/spotify/confidence/openfeature/ConfidenceFeatureProvider.kt @@ -5,6 +5,7 @@ package com.spotify.confidence.openfeature import com.spotify.confidence.Confidence import com.spotify.confidence.ConfidenceError.ErrorCode import com.spotify.confidence.ConfidenceError.FlagNotFoundError +import com.spotify.confidence.ConfidenceError.HttpError import com.spotify.confidence.ConfidenceError.ParseError import com.spotify.confidence.ConfidenceValue import com.spotify.confidence.Evaluation @@ -125,6 +126,8 @@ class ConfidenceFeatureProvider private constructor( throw OpenFeatureError.ParseError(e.message) } catch (e: FlagNotFoundError) { throw OpenFeatureError.FlagNotFoundError(e.flag) + } catch (e: HttpError) { + throw OpenFeatureError.GeneralError(e.message) } } companion object {