Skip to content

Commit

Permalink
Evaluator warning fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
z4kn4fein committed Nov 8, 2023
1 parent a00a87c commit a4cbb5f
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 112 deletions.
2 changes: 1 addition & 1 deletion src/commonMain/kotlin/com/configcat/ConfigService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ internal data class SettingResult(val settings: Map<String, Setting>?, val fetch
}
}

internal class ConfigService constructor(
internal class ConfigService(
private val options: ConfigCatOptions,
private val configFetcher: ConfigFetcher,
private val logger: InternalLogger,
Expand Down
116 changes: 50 additions & 66 deletions src/commonMain/kotlin/com/configcat/Evaluator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ internal class Evaluator(private val logger: InternalLogger) {
var error: String? = null
try {
evaluateConditionsResult = evaluateConditions(
(rule.conditions ?: arrayOf()) as Array<Any>,
rule.conditionAccessors,
rule,
setting.configSalt,
context.key,
Expand Down Expand Up @@ -162,36 +162,35 @@ internal class Evaluator(private val logger: InternalLogger) {

@Suppress("NestedBlockDepth", "CyclomaticComplexMethod", "LongMethod", "LongParameterList")
private fun evaluateConditions(
conditions: Array<Any>,
conditions: List<ConditionAccessor>,
targetingRule: TargetingRule?,
configSalt: String,
contextSalt: String,
context: EvaluationContext,
segments: Array<Segment>,
evaluateLogger: EvaluateLogger?
): Boolean {
// Conditions are ANDs so if One is not matching return false, if all matching return true
var firstConditionFlag = true
var conditionsEvaluationResult = false
var error: String? = null
var newLine = false
for (i in conditions.indices) {
val rawCondition = conditions.get(i)
if (firstConditionFlag) {
firstConditionFlag = false
evaluateLogger?.newLine()
evaluateLogger?.append("- IF ")
evaluateLogger?.increaseIndentLevel()
} else {
evaluateLogger?.increaseIndentLevel()
evaluateLogger?.newLine()
evaluateLogger?.append("AND ")
for ((index, condition) in conditions.withIndex()) {
when (index) {
0 -> {
evaluateLogger?.newLine()
evaluateLogger?.append("- IF ")
evaluateLogger?.increaseIndentLevel()
}
else -> {
evaluateLogger?.increaseIndentLevel()
evaluateLogger?.newLine()
evaluateLogger?.append("AND ")
}
}

if (targetingRule == null) {
condition.userCondition?.let { userCondition ->
try {
conditionsEvaluationResult = evaluateUserCondition(
rawCondition as UserCondition,
userCondition,
configSalt,
context,
contextSalt,
Expand All @@ -202,50 +201,38 @@ internal class Evaluator(private val logger: InternalLogger) {
conditionsEvaluationResult = false
}
newLine = conditions.size > 1
} else {
val condition = rawCondition as Condition
if (condition.userCondition != null) {
try {
conditionsEvaluationResult = evaluateUserCondition(
condition.userCondition,
configSalt,
context,
context.key,
evaluateLogger
)
} catch (evaluatorException: RolloutEvaluatorException) {
error = evaluatorException.message
conditionsEvaluationResult = false
}
newLine = conditions.size > 1
} else if (condition.segmentCondition != null) {
try {
conditionsEvaluationResult = evaluateSegmentCondition(
condition.segmentCondition,
context,
configSalt,
segments,
evaluateLogger
)
} catch (evaluatorException: RolloutEvaluatorException) {
error = evaluatorException.message
conditionsEvaluationResult = false
}
newLine = error == null || USER_OBJECT_IS_MISSING != error || conditions.size > 1
} else if (condition.prerequisiteFlagCondition != null) {
try {
conditionsEvaluationResult = evaluatePrerequisiteFlagCondition(
condition.prerequisiteFlagCondition,
context,
evaluateLogger
)
} catch (evaluatorException: RolloutEvaluatorException) {
error = evaluatorException.message
conditionsEvaluationResult = false
}
newLine = error == null || conditions.size > 1
}

condition.segmentCondition?.let { segmentCondition ->
try {
conditionsEvaluationResult = evaluateSegmentCondition(
segmentCondition,
context,
configSalt,
segments,
evaluateLogger
)
} catch (evaluatorException: RolloutEvaluatorException) {
error = evaluatorException.message
conditionsEvaluationResult = false
}
newLine = error == null || USER_OBJECT_IS_MISSING != error || conditions.size > 1
}

condition.prerequisiteFlagCondition?.let { prerequisiteCondition ->
try {
conditionsEvaluationResult = evaluatePrerequisiteFlagCondition(
prerequisiteCondition,
context,
evaluateLogger
)
} catch (evaluatorException: RolloutEvaluatorException) {
error = evaluatorException.message
conditionsEvaluationResult = false
}
newLine = error == null || conditions.size > 1
}

if (targetingRule == null || conditions.size > 1) {
evaluateLogger?.logConditionConsequence(conditionsEvaluationResult)
}
Expand All @@ -254,10 +241,10 @@ internal class Evaluator(private val logger: InternalLogger) {
break
}
}
if (targetingRule != null) {
targetingRule?.let {
evaluateLogger?.logTargetingRuleConsequence(targetingRule, error, conditionsEvaluationResult, newLine)
}
if (error != null) {
error?.let {
throw RolloutEvaluatorException(error)
}
return conditionsEvaluationResult
Expand Down Expand Up @@ -296,7 +283,7 @@ internal class Evaluator(private val logger: InternalLogger) {
@Suppress("SwallowedException")
try {
val segmentRulesResult = evaluateConditions(
segment.segmentRules as Array<Any>,
segment.conditionAccessors,
null,
configSalt,
segmentName,
Expand Down Expand Up @@ -332,10 +319,7 @@ internal class Evaluator(private val logger: InternalLogger) {
require(!prerequisiteFlagKey.isNullOrEmpty() && prerequisiteFlagSetting != null) {
"Prerequisite flag key is missing or invalid."
}
var visitedKeys: ArrayList<String>? = context.visitedKeys
if (visitedKeys == null) {
visitedKeys = ArrayList()
}
val visitedKeys: ArrayList<String> = context.visitedKeys ?: ArrayList()
visitedKeys.add(context.key)
if (visitedKeys.contains(prerequisiteFlagKey)) {
val dependencyCycle: String =
Expand Down
5 changes: 0 additions & 5 deletions src/commonMain/kotlin/com/configcat/Utils.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package com.configcat

import com.configcat.model.FlagValueSerializer
import com.soywiz.klock.DateTime
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule

internal interface Closeable {
fun close()
Expand All @@ -23,8 +21,5 @@ internal object Constants {
val distantFuture = DateTime.now().add(10_000, 0.0)
val json = Json {
ignoreUnknownKeys = true
serializersModule = SerializersModule {
contextual(Any::class, FlagValueSerializer)
}
}
}
10 changes: 4 additions & 6 deletions src/commonMain/kotlin/com/configcat/model/Condition.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ import kotlinx.serialization.Serializable
@Serializable
public data class Condition(
@SerialName(value = "u")
val userCondition: UserCondition? = null,
override val userCondition: UserCondition? = null,
@SerialName(value = "s")
val segmentCondition: SegmentCondition? = null,
override val segmentCondition: SegmentCondition? = null,
@SerialName(value = "p")
val prerequisiteFlagCondition: PrerequisiteFlagCondition? = null
) {
// No implementation
}
override val prerequisiteFlagCondition: PrerequisiteFlagCondition? = null
) : ConditionAccessor
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.configcat.model

internal interface ConditionAccessor
{
val userCondition: UserCondition?
val segmentCondition: SegmentCondition?
val prerequisiteFlagCondition: PrerequisiteFlagCondition?
}
30 changes: 0 additions & 30 deletions src/commonMain/kotlin/com/configcat/model/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,33 +33,3 @@ internal data class Config(
val empty: Config = Config(null, mapOf(), arrayOf())
}
}

internal object FlagValueSerializer : KSerializer<Any> {
override fun deserialize(decoder: Decoder): Any {
val json = decoder as? JsonDecoder
?: error("Only JsonDecoder is supported.")
val element = json.decodeJsonElement()
val primitive = element as? JsonPrimitive ?: error("Unable to decode $element")
return when (primitive.content) {
"true", "false" -> primitive.content == "true"
else -> primitive.content.toIntOrNull() ?: primitive.content.toDoubleOrNull() ?: primitive.content
}
}

override fun serialize(encoder: Encoder, value: Any) {
val json = encoder as? JsonEncoder
?: error("Only JsonEncoder is supported.")
val element: JsonElement = when (value) {
is String -> JsonPrimitive(value)
is Number -> JsonPrimitive(value)
is Boolean -> JsonPrimitive(value)
is JsonElement -> value
else -> throw IllegalArgumentException("Unable to encode $value")
}
json.encodeJsonElement(element)
}

@OptIn(ExperimentalSerializationApi::class)
override val descriptor: SerialDescriptor =
ContextualSerializer(Any::class, null, emptyArray()).descriptor
}
2 changes: 1 addition & 1 deletion src/commonMain/kotlin/com/configcat/model/Segment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ internal data class Segment(
@SerialName("r")
val segmentRules: Array<UserCondition>
) {
// No implementation
internal val conditionAccessors: List<ConditionAccessor> = segmentRules.let { condition -> condition.map { it } }
}
2 changes: 1 addition & 1 deletion src/commonMain/kotlin/com/configcat/model/TargetingRule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public data class TargetingRule(
@SerialName(value = "s")
val servedValue: ServedValue? = null
) {
// No implementation
internal val conditionAccessors: List<ConditionAccessor> = conditions?.let { condition -> condition.map { it } } ?: listOf()
}

@Serializable
Expand Down
6 changes: 4 additions & 2 deletions src/commonMain/kotlin/com/configcat/model/UserCondition.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public data class UserCondition(
*/
@SerialName("l")
val stringArrayValue: Array<String>? = null
) {
// No implementation
) : ConditionAccessor {
override val userCondition: UserCondition = this
override val segmentCondition: SegmentCondition? = null
override val prerequisiteFlagCondition: PrerequisiteFlagCondition? = null
}

0 comments on commit a4cbb5f

Please sign in to comment.