From 509ce2d9001003605f574468c30eb461e9798fa5 Mon Sep 17 00:00:00 2001 From: HARSHIT SINHA <47042785+hsinha610@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:58:15 +0530 Subject: [PATCH] Update Instance.kt --- .../kotlin/com/featurevisor/sdk/Instance.kt | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/com/featurevisor/sdk/Instance.kt b/src/main/kotlin/com/featurevisor/sdk/Instance.kt index d833849..1533ff9 100644 --- a/src/main/kotlin/com/featurevisor/sdk/Instance.kt +++ b/src/main/kotlin/com/featurevisor/sdk/Instance.kt @@ -6,6 +6,8 @@ package com.featurevisor.sdk import com.featurevisor.sdk.FeaturevisorError.MissingDatafileOptions import com.featurevisor.types.* import com.featurevisor.types.EventName.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json @@ -16,7 +18,7 @@ typealias InterceptContext = (Context) -> Context typealias DatafileFetchHandler = (datafileUrl: String) -> Result var emptyDatafile = DatafileContent( - schemaVersion = "1", + schemaVersion = "1", revision = "unknown", attributes = emptyList(), segments = emptyList(), @@ -56,6 +58,8 @@ class FeaturevisorInstance private constructor(options: InstanceOptions) { internal var configureBucketKey = options.configureBucketKey internal var configureBucketValue = options.configureBucketValue internal var refreshJob: Job? = null + private var fetchJob: Job? = null + internal val coroutineScope = CoroutineScope(Dispatchers.IO) init { with(options) { @@ -99,17 +103,26 @@ class FeaturevisorInstance private constructor(options: InstanceOptions) { } datafileUrl != null -> { - datafileReader = DatafileReader(options.datafile?: emptyDatafile) - fetchDatafileContent(datafileUrl, handleDatafileFetch) { result -> - if (result.isSuccess) { - datafileReader = DatafileReader(result.getOrThrow()) + datafileReader = DatafileReader(options.datafile ?: emptyDatafile) + fetchJob = fetchDatafileContentJob( + url = datafileUrl, + logger = logger, + handleDatafileFetch = handleDatafileFetch, + retryCount = retryCount.coerceAtLeast(1), + retryInterval = retryInterval.coerceAtLeast(0), + coroutineScope = coroutineScope, + ) { result -> + result.onSuccess { fetchResult -> + val datafileContent = fetchResult.datafileContent + datafileReader = DatafileReader(datafileContent) statuses.ready = true - emitter.emit(READY, result.getOrThrow()) + emitter.emit(READY, datafileContent, fetchResult.responseBodyString) if (refreshInterval != null) startRefreshing() - } else { - logger?.error("Failed to fetch datafile: $result") + }.onFailure { error -> + logger?.error("Failed to fetch datafile: $error") emitter.emit(ERROR) } + cancelFetchRetry() } } @@ -118,6 +131,12 @@ class FeaturevisorInstance private constructor(options: InstanceOptions) { } } + // Provide a mechanism to cancel the fetch job if retry count is more than one + fun cancelFetchRetry() { + fetchJob?.cancel() + fetchJob = null + } + fun setLogLevels(levels: List) { this.logger?.setLevels(levels) } @@ -126,14 +145,14 @@ class FeaturevisorInstance private constructor(options: InstanceOptions) { val data = datafileJSON.toByteArray(Charsets.UTF_8) try { val datafileContent = Json.decodeFromString(String(data)) - datafileReader = DatafileReader(datafileJson = datafileContent) + datafileReader = DatafileReader(datafileContent = datafileContent) } catch (e: Exception) { logger?.error("could not parse datafile", mapOf("error" to e)) } } fun setDatafile(datafileContent: DatafileContent) { - datafileReader = DatafileReader(datafileJson = datafileContent) + datafileReader = DatafileReader(datafileContent = datafileContent) } fun setStickyFeatures(stickyFeatures: StickyFeatures?) {