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

Fix issues regarding serialization and error handling #13

Merged
merged 27 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4a164ba
!wip
uniumuniu Oct 18, 2023
a1a9ecb
test commit
uniumuniu Oct 18, 2023
5b78435
Revert "test commit"
uniumuniu Oct 18, 2023
ea136a6
Finish Instance+Feature.kt and Instance+Segments.kt
uniumuniu Oct 18, 2023
2f8de11
Introduce Instance exstension functions
uniumuniu Oct 20, 2023
cc069fd
Update README.md
uniumuniu Oct 20, 2023
90d3f12
Apply codestyle
uniumuniu Oct 25, 2023
4e36ebd
Fix unit tests
uniumuniu Oct 25, 2023
6ddf82c
Add custom serializers
uniumuniu Nov 7, 2023
7cd8733
Fix deserializaing of VariableValue
uniumuniu Nov 9, 2023
be9dbcf
Merge remote-tracking branch 'origin/main' into migrate-instance
uniumuniu Nov 9, 2023
8cd4e71
types to separate package
uniumuniu Nov 9, 2023
974f79d
fix package path
uniumuniu Nov 9, 2023
9cb2cf1
clean-up
uniumuniu Nov 15, 2023
009f515
fix issues with variables
uniumuniu Nov 27, 2023
c671d5f
Remove some logs
uniumuniu Nov 29, 2023
08b5041
Fix operator serializing
uniumuniu Nov 29, 2023
9755161
Fix conditions
uniumuniu Dec 5, 2023
ec27537
Fix conditions deserialization
uniumuniu Dec 6, 2023
82641f1
Fix issues with json variables
uniumuniu Dec 8, 2023
586b962
Fix integer variable serialization
uniumuniu Dec 27, 2023
cb08f53
Fix operator
uniumuniu Dec 28, 2023
e336dfc
Fix serialization issues
uniumuniu Dec 28, 2023
2229f2d
Fix error handling
uniumuniu Dec 28, 2023
c576116
Add unit tests for serializers
uniumuniu Jan 14, 2024
c890002
Revert removing SegmentKey alias
uniumuniu Jan 14, 2024
f653af3
Remove unnecessary comments
uniumuniu Jan 14, 2024
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
3 changes: 2 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent

plugins {
// Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin.
id("org.jetbrains.kotlin.jvm") version "1.8.20"
kotlin("jvm") version "1.9.20"
kotlin("plugin.serialization") version "1.9.20"

// Apply the java-library plugin for API and implementation separation.
`java-library`
Expand Down
56 changes: 28 additions & 28 deletions src/main/kotlin/com/featurevisor/sdk/Conditions.kt
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
package com.featurevisor.sdk

import com.featurevisor.types.AttributeValue
import com.featurevisor.types.Condition
import com.featurevisor.types.Condition.And
import com.featurevisor.types.Condition.Not
import com.featurevisor.types.Condition.Or
import com.featurevisor.types.Condition.Plain
import com.featurevisor.types.ConditionValue
import com.featurevisor.types.Context
import com.featurevisor.types.Operator.AFTER
import com.featurevisor.types.Operator.BEFORE
import com.featurevisor.types.Operator.CONTAINS
import com.featurevisor.types.Operator.ENDS_WITH
import com.featurevisor.types.Operator.EQUALS
import com.featurevisor.types.Operator.GREATER_THAN
import com.featurevisor.types.Operator.GREATER_THAN_OR_EQUAL
import com.featurevisor.types.Operator.IN_ARRAY
import com.featurevisor.types.Operator.LESS_THAN
import com.featurevisor.types.Operator.LESS_THAN_OR_EQUAL
import com.featurevisor.types.Operator.NOT_CONTAINS
import com.featurevisor.types.Operator.NOT_EQUALS
import com.featurevisor.types.Operator.NOT_IN_ARRAY
import com.featurevisor.types.Operator.SEMVER_EQUALS
import com.featurevisor.types.Operator.SEMVER_GREATER_THAN
import com.featurevisor.types.Operator.SEMVER_GREATER_THAN_OR_EQUAL
import com.featurevisor.types.Operator.SEMVER_LESS_THAN
import com.featurevisor.types.Operator.SEMVER_LESS_THAN_OR_EQUAL
import com.featurevisor.types.Operator.SEMVER_NOT_EQUALS
import com.featurevisor.types.Operator.STARTS_WITH
import com.featurevisor.sdk.types.AttributeValue
uniumuniu marked this conversation as resolved.
Show resolved Hide resolved
import com.featurevisor.sdk.types.Condition
import com.featurevisor.sdk.types.Condition.And
import com.featurevisor.sdk.types.Condition.Not
import com.featurevisor.sdk.types.Condition.Or
import com.featurevisor.sdk.types.Condition.Plain
import com.featurevisor.sdk.types.ConditionValue
import com.featurevisor.sdk.types.Context
import com.featurevisor.sdk.types.Operator.AFTER
import com.featurevisor.sdk.types.Operator.BEFORE
import com.featurevisor.sdk.types.Operator.CONTAINS
import com.featurevisor.sdk.types.Operator.ENDS_WITH
import com.featurevisor.sdk.types.Operator.EQUALS
import com.featurevisor.sdk.types.Operator.GREATER_THAN
import com.featurevisor.sdk.types.Operator.GREATER_THAN_OR_EQUAL
import com.featurevisor.sdk.types.Operator.IN_ARRAY
import com.featurevisor.sdk.types.Operator.LESS_THAN
import com.featurevisor.sdk.types.Operator.LESS_THAN_OR_EQUAL
import com.featurevisor.sdk.types.Operator.NOT_CONTAINS
import com.featurevisor.sdk.types.Operator.NOT_EQUALS
import com.featurevisor.sdk.types.Operator.NOT_IN_ARRAY
import com.featurevisor.sdk.types.Operator.SEMVER_EQUALS
import com.featurevisor.sdk.types.Operator.SEMVER_GREATER_THAN
import com.featurevisor.sdk.types.Operator.SEMVER_GREATER_THAN_OR_EQUAL
import com.featurevisor.sdk.types.Operator.SEMVER_LESS_THAN
import com.featurevisor.sdk.types.Operator.SEMVER_LESS_THAN_OR_EQUAL
import com.featurevisor.sdk.types.Operator.SEMVER_NOT_EQUALS
import com.featurevisor.sdk.types.Operator.STARTS_WITH
import net.swiftzer.semver.SemVer

object Conditions {
Expand Down
15 changes: 7 additions & 8 deletions src/main/kotlin/com/featurevisor/sdk/DatafileReader.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package com.featurevisor.sdk

import com.featurevisor.types.Attribute
import com.featurevisor.types.AttributeKey
import com.featurevisor.types.DatafileContent
import com.featurevisor.types.Feature
import com.featurevisor.types.FeatureKey
import com.featurevisor.types.Segment
import com.featurevisor.types.SegmentKey
import com.featurevisor.sdk.types.Attribute
import com.featurevisor.sdk.types.AttributeKey
import com.featurevisor.sdk.types.DatafileContent
import com.featurevisor.sdk.types.Feature
import com.featurevisor.sdk.types.FeatureKey
import com.featurevisor.sdk.types.Segment

class DatafileReader constructor(
datafileJson: DatafileContent,
Expand Down Expand Up @@ -34,7 +33,7 @@ class DatafileReader constructor(
return attributes.find { attribute -> attribute.key == attributeKey }
}

fun getSegment(segmentKey: SegmentKey): Segment? {
fun getSegment(segmentKey: String): Segment? {
uniumuniu marked this conversation as resolved.
Show resolved Hide resolved
return segments.find { segment -> segment.key == segmentKey }
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/featurevisor/sdk/Emitter.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.featurevisor.sdk

import com.featurevisor.types.EventName
import com.featurevisor.sdk.types.EventName

class Emitter {

Expand Down
10 changes: 5 additions & 5 deletions src/main/kotlin/com/featurevisor/sdk/Instance+Activation.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.featurevisor.sdk

import com.featurevisor.types.AttributeValue
import com.featurevisor.types.Context
import com.featurevisor.types.EventName.ACTIVATION
import com.featurevisor.types.FeatureKey
import com.featurevisor.types.VariationValue
import com.featurevisor.sdk.types.AttributeValue
import com.featurevisor.sdk.types.Context
import com.featurevisor.sdk.types.EventName.ACTIVATION
import com.featurevisor.sdk.types.FeatureKey
import com.featurevisor.sdk.types.VariationValue

fun FeaturevisorInstance.activate(featureKey: FeatureKey, context: Context = emptyMap()): VariationValue? {
val evaluation = evaluateVariation(featureKey, context)
Expand Down
40 changes: 20 additions & 20 deletions src/main/kotlin/com/featurevisor/sdk/Instance+Evaluation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@ package com.featurevisor.sdk

import com.featurevisor.sdk.Conditions.allConditionsAreMatched
import com.featurevisor.sdk.EvaluationReason.*
import com.featurevisor.types.AttributeKey
import com.featurevisor.types.AttributeValue
import com.featurevisor.types.BucketBy
import com.featurevisor.types.BucketKey
import com.featurevisor.types.BucketValue
import com.featurevisor.types.Context
import com.featurevisor.types.Feature
import com.featurevisor.types.FeatureKey
import com.featurevisor.types.OverrideFeature
import com.featurevisor.types.Required
import com.featurevisor.types.RuleKey
import com.featurevisor.types.Traffic
import com.featurevisor.types.VariableKey
import com.featurevisor.types.VariableSchema
import com.featurevisor.types.VariableValue
import com.featurevisor.types.Variation
import com.featurevisor.types.VariationValue
import com.featurevisor.sdk.types.AttributeKey
import com.featurevisor.sdk.types.AttributeValue
import com.featurevisor.sdk.types.BucketBy
import com.featurevisor.sdk.types.BucketKey
import com.featurevisor.sdk.types.BucketValue
import com.featurevisor.sdk.types.Context
import com.featurevisor.sdk.types.Feature
import com.featurevisor.sdk.types.FeatureKey
import com.featurevisor.sdk.types.OverrideFeature
import com.featurevisor.sdk.types.Required
import com.featurevisor.sdk.types.RuleKey
import com.featurevisor.sdk.types.Traffic
import com.featurevisor.sdk.types.VariableKey
import com.featurevisor.sdk.types.VariableSchema
import com.featurevisor.sdk.types.VariableValue
import com.featurevisor.sdk.types.Variation
import com.featurevisor.sdk.types.VariationValue
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromJsonElement
Expand Down Expand Up @@ -612,7 +612,7 @@ private fun FeaturevisorInstance.getBucketKey(feature: Feature, context: Context

is BucketBy.Or -> {
type = "or"
attributeKeys = bucketBy.bucketBy.or
attributeKeys = bucketBy.bucketBy
}
}

Expand All @@ -632,9 +632,9 @@ private fun FeaturevisorInstance.getBucketKey(feature: Feature, context: Context

bucketKey.add(AttributeValue.StringValue(featureKey))

val result = bucketKey.map {
val result = bucketKey.joinToString(separator = bucketKeySeparator) {
it.toString()
}.joinToString(separator = bucketKeySeparator)
}

configureBucketKey?.let { configureBucketKey ->
return configureBucketKey(feature, context, result)
Expand Down
12 changes: 6 additions & 6 deletions src/main/kotlin/com/featurevisor/sdk/Instance+Feature.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.featurevisor.sdk

import com.featurevisor.sdk.Conditions.allConditionsAreMatched
import com.featurevisor.types.Allocation
import com.featurevisor.types.Context
import com.featurevisor.types.Feature
import com.featurevisor.types.Force
import com.featurevisor.types.Traffic
import com.featurevisor.sdk.types.Allocation
import com.featurevisor.sdk.types.Context
import com.featurevisor.sdk.types.Feature
import com.featurevisor.sdk.types.Force
import com.featurevisor.sdk.types.Traffic

internal fun FeaturevisorInstance.getFeatureByKey(featureKey: String): Feature? {
fun FeaturevisorInstance.getFeatureByKey(featureKey: String): Feature? {
return datafileReader.getFeature(featureKey)
}

Expand Down
31 changes: 23 additions & 8 deletions src/main/kotlin/com/featurevisor/sdk/Instance+Fetch.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.featurevisor.sdk

import com.featurevisor.types.DatafileContent
import com.featurevisor.sdk.types.DatafileContent
import java.io.IOException
import okhttp3.*
import kotlinx.serialization.json.Json
Expand Down Expand Up @@ -39,21 +39,36 @@ private fun fetchDatafileContentFromUrl(
}
}

private inline fun <reified T> fetch(
const val BODY_BYTE_COUNT = 1000000L
private inline fun fetch(
request: Request,
crossinline completion: (Result<T>) -> Unit,
crossinline completion: (Result<DatafileContent>) -> Unit,
) {
val client = OkHttpClient()
val call = client.newCall(request)
call.enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
val responseBody = response.body
if (response.isSuccessful && responseBody != null) {
val json = Json { ignoreUnknownKeys = true }
val content = json.decodeFromString<T>(responseBody.string())
val responseBody = response.peekBody(BODY_BYTE_COUNT)
if (response.isSuccessful) {
val json = Json {
ignoreUnknownKeys = true
serializersModule = this.serializersModule.apply {

}
}
val responseBodyString = responseBody.string()
FeaturevisorInstance.companionLogger?.debug(responseBodyString)
val content = json.decodeFromString<DatafileContent>(responseBodyString)
completion(Result.success(content))
} else {
completion(Result.failure(FeaturevisorError.UnparsableJson(responseBody?.string(), response.message)))
completion(
Result.failure(
FeaturevisorError.UnparsableJson(
responseBody.string(),
response.message
)
)
)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/featurevisor/sdk/Instance+Refresh.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.featurevisor.sdk

import com.featurevisor.sdk.FeaturevisorError.*
import com.featurevisor.types.EventName
import com.featurevisor.sdk.types.EventName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
Expand Down
12 changes: 6 additions & 6 deletions src/main/kotlin/com/featurevisor/sdk/Instance+Segments.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.featurevisor.sdk

import com.featurevisor.sdk.Conditions.allConditionsAreMatched
import com.featurevisor.types.Context
import com.featurevisor.types.FeatureKey
import com.featurevisor.types.GroupSegment
import com.featurevisor.types.GroupSegment.*
import com.featurevisor.types.Segment
import com.featurevisor.types.VariationValue
import com.featurevisor.sdk.types.Context
import com.featurevisor.sdk.types.FeatureKey
import com.featurevisor.sdk.types.GroupSegment
import com.featurevisor.sdk.types.GroupSegment.*
import com.featurevisor.sdk.types.Segment
import com.featurevisor.sdk.types.VariationValue

internal fun FeaturevisorInstance.segmentIsMatched(
featureKey: FeatureKey,
Expand Down
10 changes: 5 additions & 5 deletions src/main/kotlin/com/featurevisor/sdk/Instance+Variable.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.featurevisor.sdk

import com.featurevisor.types.Context
import com.featurevisor.types.FeatureKey
import com.featurevisor.types.VariableKey
import com.featurevisor.types.VariableValue
import com.featurevisor.types.VariableValue.*
import com.featurevisor.sdk.types.Context
import com.featurevisor.sdk.types.FeatureKey
import com.featurevisor.sdk.types.VariableKey
import com.featurevisor.sdk.types.VariableValue
import com.featurevisor.sdk.types.VariableValue.*
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.encodeToJsonElement
Expand Down
6 changes: 3 additions & 3 deletions src/main/kotlin/com/featurevisor/sdk/Instance+Variation.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.featurevisor.sdk

import com.featurevisor.types.Context
import com.featurevisor.types.FeatureKey
import com.featurevisor.types.VariationValue
import com.featurevisor.sdk.types.Context
import com.featurevisor.sdk.types.FeatureKey
import com.featurevisor.sdk.types.VariationValue

internal fun FeaturevisorInstance.getVariation(featureKey: FeatureKey, context: Context): VariationValue? {
val evaluation = evaluateVariation(featureKey, context)
Expand Down
27 changes: 15 additions & 12 deletions src/main/kotlin/com/featurevisor/sdk/Instance.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ package com.featurevisor.sdk

import com.featurevisor.sdk.FeaturevisorError.FetchingDataFileFailed
import com.featurevisor.sdk.FeaturevisorError.MissingDatafileOptions
import com.featurevisor.types.BucketKey
import com.featurevisor.types.BucketValue
import com.featurevisor.types.Context
import com.featurevisor.types.DatafileContent
import com.featurevisor.types.EventName
import com.featurevisor.types.EventName.ACTIVATION
import com.featurevisor.types.EventName.READY
import com.featurevisor.types.EventName.REFRESH
import com.featurevisor.types.EventName.UPDATE
import com.featurevisor.types.Feature
import com.featurevisor.types.StickyFeatures
import com.featurevisor.sdk.types.BucketKey
import com.featurevisor.sdk.types.BucketValue
import com.featurevisor.sdk.types.Context
import com.featurevisor.sdk.types.DatafileContent
import com.featurevisor.sdk.types.EventName
import com.featurevisor.sdk.types.EventName.ACTIVATION
import com.featurevisor.sdk.types.EventName.READY
import com.featurevisor.sdk.types.EventName.REFRESH
import com.featurevisor.sdk.types.EventName.UPDATE
import com.featurevisor.sdk.types.Feature
import com.featurevisor.sdk.types.StickyFeatures
import kotlinx.coroutines.Job
import kotlinx.serialization.json.Json

Expand All @@ -30,6 +30,8 @@ class FeaturevisorInstance private constructor(options: InstanceOptions) {
fun createInstance(options: InstanceOptions): FeaturevisorInstance {
return FeaturevisorInstance(options)
}

var companionLogger: Logger? = null
}

private val on: (EventName, Listener) -> Unit
Expand Down Expand Up @@ -58,6 +60,7 @@ class FeaturevisorInstance private constructor(options: InstanceOptions) {

init {
with(options) {
companionLogger = logger
if (onReady != null) {
emitter.addListener(event = READY, listener = onReady)
}
Expand Down Expand Up @@ -96,7 +99,7 @@ class FeaturevisorInstance private constructor(options: InstanceOptions) {
if (result.isSuccess) {
datafileReader = DatafileReader(result.getOrThrow())
statuses.ready = true
emitter.emit(READY)
emitter.emit(READY, result.getOrThrow())
if (refreshInterval != null) startRefreshing()
} else {
logger?.error("Failed to fetch datafile: $result")
Expand Down
6 changes: 3 additions & 3 deletions src/main/kotlin/com/featurevisor/sdk/InstanceOptions.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.featurevisor.sdk

import com.featurevisor.types.DatafileContent
import com.featurevisor.types.InitialFeatures
import com.featurevisor.types.StickyFeatures
import com.featurevisor.sdk.types.DatafileContent
import com.featurevisor.sdk.types.InitialFeatures
import com.featurevisor.sdk.types.StickyFeatures

typealias Listener = (Array<out Any>) -> Unit

Expand Down
Loading
Loading