Skip to content

Commit

Permalink
refactor!: context container in event payload (#158)
Browse files Browse the repository at this point in the history
refactor!: context container in payload
  • Loading branch information
fabriziodemaria authored May 29, 2024
1 parent 06b4d5f commit fd54e21
Showing 13 changed files with 72 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.spotify.confidence

import android.content.Context
import com.spotify.confidence.ConfidenceError.ParseError
import com.spotify.confidence.apply.FlagApplierWithRetries
import com.spotify.confidence.cache.DiskStorage
import com.spotify.confidence.cache.FileDiskStorage
26 changes: 26 additions & 0 deletions Confidence/src/main/java/com/spotify/confidence/ConfidenceError.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.spotify.confidence

class ConfidenceError {
enum class ErrorCode {
// The value was resolved before the provider was ready.
RESOLVE_STALE,

// The flag could not be found.
FLAG_NOT_FOUND,
INVALID_CONTEXT,
PROVIDER_NOT_READY,
PARSE_ERROR
}

data class ParseError(
override val message: String,
val flagPaths: List<String> = listOf()
) : Error(message)

data class FlagNotFoundError(
override val message: String,
val flag: String
) : Error(message)

class InvalidContextInMessage : Error("Field 'context' is not allowed in event's data")
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.spotify.confidence

import com.spotify.confidence.ConfidenceError.ErrorCode

fun <T> FlagResolution?.getEvaluation(
flag: String,
defaultValue: T,
@@ -107,24 +109,4 @@ private data class FlagKey(
)
}
}
}

enum class ErrorCode {
// The value was resolved before the provider was ready.
RESOLVE_STALE,

// The flag could not be found.
FLAG_NOT_FOUND,
INVALID_CONTEXT,
PROVIDER_NOT_READY,
PARSE_ERROR
}

data class ParseError(
override val message: String,
val flagPaths: List<String> = listOf()
) : Error(message)
data class FlagNotFoundError(
override val message: String,
val flag: String
) : Error(message)
}
Original file line number Diff line number Diff line change
@@ -104,10 +104,11 @@ internal class EventSenderEngineImpl(
context: Map<String, ConfidenceValue>
) {
coroutineScope.launch {
val payload = payloadMerger(context, data)
val event = EngineEvent(
eventDefinition = eventName,
eventTime = clock.currentTime(),
payload = payloadMerger(context, data)
payload = payload
)
writeReqChannel.send(event)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.spotify.confidence

import com.spotify.confidence.ConfidenceError.ErrorCode
import com.spotify.confidence.client.ConfidenceValueMap
import com.spotify.confidence.client.ResolvedFlag
import kotlinx.serialization.Serializable
Original file line number Diff line number Diff line change
@@ -3,6 +3,10 @@ package com.spotify.confidence
private typealias ConfidenceStruct = Map<String, ConfidenceValue>
internal interface PayloadMerger : (ConfidenceStruct, ConfidenceStruct) -> ConfidenceStruct
internal class PayloadMergerImpl : PayloadMerger {
override fun invoke(context: ConfidenceStruct, message: ConfidenceStruct): ConfidenceStruct =
context + message
override fun invoke(context: ConfidenceStruct, message: ConfidenceStruct): ConfidenceStruct {
if (message.containsKey("context")) {
throw ConfidenceError.InvalidContextInMessage()
}
return message + (mapOf("context" to ConfidenceValue.Struct(context)))
}
}
Original file line number Diff line number Diff line change
@@ -90,5 +90,5 @@ private fun Response.toResolveFlags(): ResolveResponse {
}
}
return ResolveResponse.Resolved(networkJson.decodeFromString(bodyString))
} ?: throw ParseError("Response body is null", listOf())
} ?: throw ConfidenceError.ParseError("Response body is null", listOf())
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.spotify.confidence.serializers

import android.annotation.SuppressLint
import com.spotify.confidence.ConfidenceError.ParseError
import com.spotify.confidence.ConfidenceValue
import com.spotify.confidence.ParseError
import com.spotify.confidence.ResolveReason
import com.spotify.confidence.client.Flags
import com.spotify.confidence.client.ResolvedFlag
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.spotify.confidence

import android.content.Context
import com.spotify.confidence.ConfidenceError.ErrorCode
import com.spotify.confidence.apply.EventStatus
import com.spotify.confidence.apply.FlagsAppliedMap
import com.spotify.confidence.cache.FileDiskStorage
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@

package com.spotify.confidence

import com.spotify.confidence.ConfidenceError.ParseError
import com.spotify.confidence.client.AppliedFlag
import com.spotify.confidence.client.Clock
import com.spotify.confidence.client.FlagApplierClientImpl
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package com.spotify.confidence

import android.content.Context
import android.content.SharedPreferences
import com.spotify.confidence.ConfidenceError.InvalidContextInMessage
import com.spotify.confidence.client.SdkMetadata
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
@@ -42,6 +43,17 @@ class EventSenderIntegrationTest {
}
}

@Test(expected = InvalidContextInMessage::class)
fun context_in_message_throws() = runTest {
val testDispatcher = UnconfinedTestDispatcher(testScheduler)
val confidence = ConfidenceFactory.create(
mockContext,
clientSecret,
dispatcher = testDispatcher
)
confidence.track("test", mapOf("context" to ConfidenceValue.Integer(1)))
}

@Test
fun created_event_sender_has_visitor_id_context() = runTest {
val testDispatcher = UnconfinedTestDispatcher(testScheduler)
@@ -183,20 +195,24 @@ class EventSenderIntegrationTest {
engine.emit(
eventName = "my_event",
data = mapOf(
"a" to ConfidenceValue.Integer(0),
"message" to ConfidenceValue.Integer(1)
"a" to ConfidenceValue.Integer(0)
),
context = mapOf(
"a" to ConfidenceValue.Integer(2),
"message" to ConfidenceValue.Integer(3)
"b" to ConfidenceValue.Integer(3)
)
)
advanceUntilIdle()
Assert.assertEquals("eventDefinitions/my_event", uploadedEvents[0].eventDefinition)
Assert.assertEquals(
mapOf(
"a" to ConfidenceValue.Integer(0),
"message" to ConfidenceValue.Integer(1)
"context" to ConfidenceValue.Struct(
mapOf(
"a" to ConfidenceValue.Integer(2),
"b" to ConfidenceValue.Integer(3)
)
)
),
uploadedEvents[0].payload
)
Original file line number Diff line number Diff line change
@@ -11,10 +11,13 @@ class PayloadMergerTest {
val result = payloadMerger(context, message)
assert(
result == mapOf(
"a" to ConfidenceValue.Integer(1),
"b" to ConfidenceValue.Integer(3),
"c" to ConfidenceValue.Integer(
4
"c" to ConfidenceValue.Integer(4),
"context" to ConfidenceValue.Struct(
mapOf(
"a" to ConfidenceValue.Integer(1),
"b" to ConfidenceValue.Integer(2)
)
)
)
)
Original file line number Diff line number Diff line change
@@ -2,11 +2,11 @@
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.ParseError
import com.spotify.confidence.ConfidenceValue
import com.spotify.confidence.ErrorCode
import com.spotify.confidence.Evaluation
import com.spotify.confidence.FlagNotFoundError
import com.spotify.confidence.ParseError
import com.spotify.confidence.ResolveReason
import dev.openfeature.sdk.EvaluationContext
import dev.openfeature.sdk.FeatureProvider

0 comments on commit fd54e21

Please sign in to comment.