From dcfc81904b25ed7530a2b4b44163d2b9a5541976 Mon Sep 17 00:00:00 2001 From: Tanmay Ranjan Date: Thu, 4 Apr 2024 12:11:53 +0530 Subject: [PATCH] Try catch handled in all extension function --- .../com/featurevisor/sdk/DatafileReader.kt | 2 +- .../featurevisor/sdk/Instance+Activation.kt | 44 +++++----- .../com/featurevisor/sdk/Instance+Feature.kt | 81 ++++++++++++------- .../com/featurevisor/sdk/Instance+Fetch.kt | 14 ++-- .../com/featurevisor/sdk/Instance+Segments.kt | 75 +++++++++-------- .../com/featurevisor/sdk/Instance+Variable.kt | 25 ++++-- .../featurevisor/sdk/Instance+Variation.kt | 14 ++-- .../kotlin/com/featurevisor/sdk/Instance.kt | 67 +++++++++++++++ 8 files changed, 221 insertions(+), 101 deletions(-) diff --git a/src/main/kotlin/com/featurevisor/sdk/DatafileReader.kt b/src/main/kotlin/com/featurevisor/sdk/DatafileReader.kt index eef4c77..b9eb953 100644 --- a/src/main/kotlin/com/featurevisor/sdk/DatafileReader.kt +++ b/src/main/kotlin/com/featurevisor/sdk/DatafileReader.kt @@ -8,7 +8,7 @@ import com.featurevisor.types.FeatureKey import com.featurevisor.types.Segment import com.featurevisor.types.SegmentKey -class DatafileReader constructor( +class DatafileReader ( datafileJson: DatafileContent, ) { diff --git a/src/main/kotlin/com/featurevisor/sdk/Instance+Activation.kt b/src/main/kotlin/com/featurevisor/sdk/Instance+Activation.kt index 3454b0b..ba13213 100644 --- a/src/main/kotlin/com/featurevisor/sdk/Instance+Activation.kt +++ b/src/main/kotlin/com/featurevisor/sdk/Instance+Activation.kt @@ -7,27 +7,31 @@ import com.featurevisor.types.FeatureKey import com.featurevisor.types.VariationValue fun FeaturevisorInstance.activate(featureKey: FeatureKey, context: Context = emptyMap()): VariationValue? { - val evaluation = evaluateVariation(featureKey, context) - val variationValue = evaluation.variation?.value ?: evaluation.variationValue ?: return null - val finalContext = interceptContext?.invoke(context) ?: context - val captureContext = mutableMapOf() - val attributesForCapturing = datafileReader.getAllAttributes() - .filter { it.capture == true } + return try { + val evaluation = evaluateVariation(featureKey, context) + val variationValue = evaluation.variation?.value ?: evaluation.variationValue ?: return null + val finalContext = interceptContext?.invoke(context) ?: context + val captureContext = mutableMapOf() + val attributesForCapturing = datafileReader.getAllAttributes() + .filter { it.capture == true } - attributesForCapturing.forEach { attribute -> - finalContext[attribute.key]?.let { - captureContext[attribute.key] = it - } - } + attributesForCapturing.forEach { attribute -> + finalContext[attribute.key]?.let { + captureContext[attribute.key] = it + } + } - emitter.emit( - ACTIVATION, - featureKey, - variationValue, - finalContext, - captureContext, - evaluation - ) + emitter.emit( + ACTIVATION, + featureKey, + variationValue, + finalContext, + captureContext, + evaluation + ) - return variationValue + variationValue + }catch (e:Exception){ + null + } } diff --git a/src/main/kotlin/com/featurevisor/sdk/Instance+Feature.kt b/src/main/kotlin/com/featurevisor/sdk/Instance+Feature.kt index 46cd705..01b3478 100644 --- a/src/main/kotlin/com/featurevisor/sdk/Instance+Feature.kt +++ b/src/main/kotlin/com/featurevisor/sdk/Instance+Feature.kt @@ -8,11 +8,19 @@ import com.featurevisor.types.Force import com.featurevisor.types.Traffic fun FeaturevisorInstance.getFeatureByKey(featureKey: String): Feature? { - return datafileReader.getFeature(featureKey) + return try { + datafileReader.getFeature(featureKey) + }catch (e:Exception){ + null + } } fun FeaturevisorInstance.getFeature(featureKey: String): Feature?{ - return datafileReader.getFeature(featureKey) + return try { + datafileReader.getFeature(featureKey) + }catch (e:Exception){ + null + } } internal fun FeaturevisorInstance.findForceFromFeature( @@ -20,18 +28,21 @@ internal fun FeaturevisorInstance.findForceFromFeature( context: Context, datafileReader: DatafileReader, ): Force? { + return try { + feature.force?.firstOrNull { force -> + when { + force.conditions != null -> allConditionsAreMatched(force.conditions, context) + force.segments != null -> allGroupSegmentsAreMatched( + force.segments, + context, + datafileReader + ) - return feature.force?.firstOrNull { force -> - when { - force.conditions != null -> allConditionsAreMatched(force.conditions, context) - force.segments != null -> allGroupSegmentsAreMatched( - force.segments, - context, - datafileReader - ) - - else -> false + else -> false + } } + }catch (e:Exception){ + null } } @@ -40,9 +51,12 @@ internal fun FeaturevisorInstance.getMatchedTraffic( context: Context, datafileReader: DatafileReader, ): Traffic? { - - return traffic.firstOrNull { trafficItem -> - allGroupSegmentsAreMatched(trafficItem.segments, context, datafileReader) + return try { + traffic.firstOrNull { trafficItem -> + allGroupSegmentsAreMatched(trafficItem.segments, context, datafileReader) + } + }catch (e:Exception){ + null } } @@ -50,17 +64,20 @@ internal fun FeaturevisorInstance.getMatchedAllocation( traffic: Traffic, bucketValue: Int, ): Allocation? { - - return traffic.allocation.firstOrNull { allocation -> - with(allocation.range) { - bucketValue in this.first()..this.last() + return try { + traffic.allocation.firstOrNull { allocation -> + with(allocation.range) { + bucketValue in this.first()..this.last() + } } + }catch (e:Exception){ + null } } data class MatchedTrafficAndAllocation( - val matchedTraffic: Traffic?, - val matchedAllocation: Allocation?, + val matchedTraffic: Traffic?=null, + val matchedAllocation: Allocation?=null, ) internal fun FeaturevisorInstance.getMatchedTrafficAndAllocation( @@ -70,16 +87,18 @@ internal fun FeaturevisorInstance.getMatchedTrafficAndAllocation( datafileReader: DatafileReader, logger: Logger?, ): MatchedTrafficAndAllocation { - - var matchedAllocation: Allocation? = null - val matchedTraffic = traffic.firstOrNull { trafficItem -> - if (allGroupSegmentsAreMatched(trafficItem.segments, context, datafileReader)) { - matchedAllocation = getMatchedAllocation(trafficItem, bucketValue) - true - } else { - false + return try { + var matchedAllocation: Allocation? = null + val matchedTraffic = traffic.firstOrNull { trafficItem -> + if (allGroupSegmentsAreMatched(trafficItem.segments, context, datafileReader)) { + matchedAllocation = getMatchedAllocation(trafficItem, bucketValue) + true + } else { + false + } } + MatchedTrafficAndAllocation(matchedTraffic, matchedAllocation) + }catch (e:Exception){ + MatchedTrafficAndAllocation() } - - return MatchedTrafficAndAllocation(matchedTraffic, matchedAllocation) } diff --git a/src/main/kotlin/com/featurevisor/sdk/Instance+Fetch.kt b/src/main/kotlin/com/featurevisor/sdk/Instance+Fetch.kt index ea950c8..911ad6e 100644 --- a/src/main/kotlin/com/featurevisor/sdk/Instance+Fetch.kt +++ b/src/main/kotlin/com/featurevisor/sdk/Instance+Fetch.kt @@ -15,11 +15,15 @@ internal fun FeaturevisorInstance.fetchDatafileContent( handleDatafileFetch: DatafileFetchHandler? = null, completion: (Result) -> Unit, ) { - handleDatafileFetch?.let { handleFetch -> - val result = handleFetch(url) - completion(result) - } ?: run { - fetchDatafileContentFromUrl(url, completion) + try { + handleDatafileFetch?.let { handleFetch -> + val result = handleFetch(url) + completion(result) + } ?: run { + fetchDatafileContentFromUrl(url, completion) + } + }catch (e:Exception){ + completion(Result.failure(FeaturevisorError.InvalidUrl(url))) } } diff --git a/src/main/kotlin/com/featurevisor/sdk/Instance+Segments.kt b/src/main/kotlin/com/featurevisor/sdk/Instance+Segments.kt index b71d893..9946c83 100644 --- a/src/main/kotlin/com/featurevisor/sdk/Instance+Segments.kt +++ b/src/main/kotlin/com/featurevisor/sdk/Instance+Segments.kt @@ -12,17 +12,22 @@ internal fun FeaturevisorInstance.segmentIsMatched( featureKey: FeatureKey, context: Context, ): VariationValue? { - val evaluation = evaluateVariation(featureKey, context) + return try { + val evaluation = evaluateVariation(featureKey, context) + var variationValue: VariationValue? = null - if (evaluation.variationValue != null) { - return evaluation.variationValue - } + if (evaluation.variationValue != null) { + variationValue = evaluation.variationValue + } - if (evaluation.variation != null) { - return evaluation.variation.value - } + if (evaluation.variation != null) { + variationValue = evaluation.variation.value + } - return null + variationValue + } catch (e: Exception) { + null + } } internal fun segmentIsMatched(segment: Segment, context: Context): Boolean { @@ -34,40 +39,44 @@ internal fun FeaturevisorInstance.allGroupSegmentsAreMatched( context: Context, datafileReader: DatafileReader, ): Boolean { - return when (groupSegments) { - is Plain -> { - val segmentKey = groupSegments.segment - if (segmentKey == "*") { - true - } else { - datafileReader.getSegment(segmentKey)?.let { - segmentIsMatched(it, context) - } ?: false + return try { + when (groupSegments) { + is Plain -> { + val segmentKey = groupSegments.segment + if (segmentKey == "*") { + true + } else { + datafileReader.getSegment(segmentKey)?.let { + segmentIsMatched(it, context) + } ?: false + } } - } - is Multiple -> { - groupSegments.segments.all { - allGroupSegmentsAreMatched(it, context, datafileReader) + is Multiple -> { + groupSegments.segments.all { + allGroupSegmentsAreMatched(it, context, datafileReader) + } } - } - is And -> { - groupSegments.segment.and.all { - allGroupSegmentsAreMatched(it, context, datafileReader) + is And -> { + groupSegments.segment.and.all { + allGroupSegmentsAreMatched(it, context, datafileReader) + } } - } - is Or -> { - groupSegments.segment.or.any { - allGroupSegmentsAreMatched(it, context, datafileReader) + is Or -> { + groupSegments.segment.or.any { + allGroupSegmentsAreMatched(it, context, datafileReader) + } } - } - is Not -> { - groupSegments.segment.not.all { - allGroupSegmentsAreMatched(it, context, datafileReader).not() + is Not -> { + groupSegments.segment.not.all { + allGroupSegmentsAreMatched(it, context, datafileReader).not() + } } } + }catch (e:Exception){ + false } } diff --git a/src/main/kotlin/com/featurevisor/sdk/Instance+Variable.kt b/src/main/kotlin/com/featurevisor/sdk/Instance+Variable.kt index 925f20d..16fd2e5 100644 --- a/src/main/kotlin/com/featurevisor/sdk/Instance+Variable.kt +++ b/src/main/kotlin/com/featurevisor/sdk/Instance+Variable.kt @@ -11,6 +11,7 @@ import com.featurevisor.types.VariableValue.IntValue import com.featurevisor.types.VariableValue.JsonValue import com.featurevisor.types.VariableValue.ObjectValue import com.featurevisor.types.VariableValue.StringValue +import kotlinx.serialization.Serializable import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import kotlinx.serialization.json.decodeFromJsonElement @@ -21,13 +22,17 @@ fun FeaturevisorInstance.getVariable( variableKey: VariableKey, context: Context = emptyMap(), ): VariableValue? { - val evaluation = evaluateVariable( - featureKey = featureKey, - variableKey = variableKey, - context = context - ) + return try { + val evaluation = evaluateVariable( + featureKey = featureKey, + variableKey = variableKey, + context = context + ) - return evaluation.variableValue + evaluation.variableValue + } catch (e: Exception) { + null + } } fun FeaturevisorInstance.getVariableBoolean( @@ -97,3 +102,11 @@ inline fun FeaturevisorInstance.getVariableJSON( } } +@Serializable +data class CountriesWithStringValueAndSeparateDefault( + val country: Map?, + val default: String?, +) + + + diff --git a/src/main/kotlin/com/featurevisor/sdk/Instance+Variation.kt b/src/main/kotlin/com/featurevisor/sdk/Instance+Variation.kt index 5a9eb2a..dcb83a1 100644 --- a/src/main/kotlin/com/featurevisor/sdk/Instance+Variation.kt +++ b/src/main/kotlin/com/featurevisor/sdk/Instance+Variation.kt @@ -5,10 +5,14 @@ import com.featurevisor.types.FeatureKey import com.featurevisor.types.VariationValue internal fun FeaturevisorInstance.getVariation(featureKey: FeatureKey, context: Context): VariationValue? { - val evaluation = evaluateVariation(featureKey, context) - return when { - evaluation.variationValue != null -> evaluation.variationValue - evaluation.variation != null -> evaluation.variation.value - else -> null + return try { + val evaluation = evaluateVariation(featureKey, context) + return when { + evaluation.variationValue != null -> evaluation.variationValue + evaluation.variation != null -> evaluation.variation.value + else -> null + } + }catch (e:Exception){ + null } } diff --git a/src/main/kotlin/com/featurevisor/sdk/Instance.kt b/src/main/kotlin/com/featurevisor/sdk/Instance.kt index 9e9b2b1..bdbbf86 100644 --- a/src/main/kotlin/com/featurevisor/sdk/Instance.kt +++ b/src/main/kotlin/com/featurevisor/sdk/Instance.kt @@ -7,6 +7,7 @@ import com.featurevisor.sdk.FeaturevisorError.MissingDatafileOptions import com.featurevisor.types.* import com.featurevisor.types.EventName.* import kotlinx.coroutines.Job +import kotlinx.serialization.Serializable import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json @@ -15,6 +16,72 @@ typealias ConfigureBucketValue = (Feature, Context, BucketValue) -> BucketValue typealias InterceptContext = (Context) -> Context typealias DatafileFetchHandler = (datafileUrl: String) -> Result +fun main(args: Array) { + + var abc:FeaturevisorInstance? = null + var isReady:Boolean = false + abc = FeaturevisorInstance.createInstance( + options = InstanceOptions( + configureBucketKey = null, + configureBucketValue = null, + datafileUrl = "https://features.fe.indazn.com/staging/datafile-tag-android.json", + logger = Logger.createLogger( + levels = listOf( + Logger.LogLevel.ERROR, + Logger.LogLevel.DEBUG, + Logger.LogLevel.WARN, + Logger.LogLevel.INFO + ) , + handle = { _, message, _ -> + println(message) + } + ), +// onReady = { +// isReady = true +// println("onReady $it") +// +// val value = abc?.getVariableJSON("live_preroll_ads","live_preroll_ads_custom_tags", getContext()) +// println("Value : $value") +// +// }, +// onError = { +// println("onError $it") +// } + ) + ) + + + val value = abc?.getVariableJSON("live_preroll_ads","live_preroll_ads_custom_tags", getContext()) + println("Value : $value") + + +// if (isReady){ +// val value = abc.getVariableJSON>("live_preroll_ads","live_preroll_watched_duration", getContext()) +// println("Value : $value") +// }else{ +// println("Not Ready") +// } + +} + + +private fun getContext(): Map = + mapOf( + "deviceId" to AttributeValue.StringValue("45645"), + "version_code" to AttributeValue.StringValue(""), + "app_info_version" to AttributeValue.StringValue(""), + "Platform" to AttributeValue.StringValue("Android"), + "BillingCountry" to AttributeValue.StringValue("In"), + "GeolocatedCountry" to AttributeValue.StringValue("In"), + "device_os" to AttributeValue.StringValue("Android"), + "DevMode" to AttributeValue.BooleanValue(false), + "device_model" to AttributeValue.StringValue("5dfgfcx"), + "device_language" to AttributeValue.StringValue("en"), + "user_status" to AttributeValue.StringValue("Active") + ) + + + class FeaturevisorInstance private constructor(options: InstanceOptions) { companion object {