diff --git a/sdk/src/main/java/com/amplitude/experiment/DefaultExperimentClient.kt b/sdk/src/main/java/com/amplitude/experiment/DefaultExperimentClient.kt index 54b8cd6..81935ea 100644 --- a/sdk/src/main/java/com/amplitude/experiment/DefaultExperimentClient.kt +++ b/sdk/src/main/java/com/amplitude/experiment/DefaultExperimentClient.kt @@ -4,7 +4,6 @@ import com.amplitude.experiment.evaluation.EvaluationEngineImpl import com.amplitude.experiment.evaluation.EvaluationFlag import com.amplitude.experiment.evaluation.json import com.amplitude.experiment.evaluation.topologicalSort -import com.amplitude.experiment.storage.LoadStoreCache import com.amplitude.experiment.storage.Storage import com.amplitude.experiment.storage.getFlagStorage import com.amplitude.experiment.storage.getVariantStorage @@ -59,23 +58,31 @@ internal class DefaultExperimentClient internal constructor( private var user: ExperimentUser? = null private val engine = EvaluationEngineImpl() - private val variants: LoadStoreCache = + private val variants = getVariantStorage( this.apiKey, this.config.instanceName, storage, ) - private val flags: LoadStoreCache = + private val flags = getFlagStorage( this.apiKey, this.config.instanceName, storage, + ::mergeInitialFlagsWithStorage, ) init { - this.variants.load() - this.flags.load() - mergeInitialFlagsWithStorage() + executorService.execute { + synchronized(variants) { + this.variants.load() + } + } + executorService.execute { + synchronized(flags) { + this.flags.load() + } + } } private val backoffLock = Any() diff --git a/sdk/src/main/java/com/amplitude/experiment/Experiment.kt b/sdk/src/main/java/com/amplitude/experiment/Experiment.kt index 04d689f..3585e09 100644 --- a/sdk/src/main/java/com/amplitude/experiment/Experiment.kt +++ b/sdk/src/main/java/com/amplitude/experiment/Experiment.kt @@ -17,7 +17,7 @@ object Experiment { isDaemon = true } } - internal val executorService = ScheduledThreadPoolExecutor(2, daemonThreadFactory) + internal val executorService = ScheduledThreadPoolExecutor(4, daemonThreadFactory) private val httpClient = OkHttpClient() private val instances = mutableMapOf() diff --git a/sdk/src/main/java/com/amplitude/experiment/storage/Cache.kt b/sdk/src/main/java/com/amplitude/experiment/storage/Cache.kt index e4fa3b6..17993b7 100644 --- a/sdk/src/main/java/com/amplitude/experiment/storage/Cache.kt +++ b/sdk/src/main/java/com/amplitude/experiment/storage/Cache.kt @@ -13,14 +13,18 @@ internal class LoadStoreCache( private val storage: Storage, private val decoder: ((value: String) -> V?), private val encoder: ((value: V) -> String), + private val onLoad: (() -> Unit)? = null, ) { private val cache: MutableMap = mutableMapOf() + private var isLoaded = false fun get(key: String): V? { + if (!isLoaded) load() return cache[key] } fun getAll(): Map { + if (!isLoaded) load() return HashMap(cache) } @@ -60,6 +64,8 @@ internal class LoadStoreCache( }.toMap() clear() putAll(values) + isLoaded = true + onLoad?.invoke() } fun store(values: MutableMap = cache) { @@ -94,10 +100,11 @@ internal fun getFlagStorage( deploymentKey: String, instanceName: String, storage: Storage, + merger: () -> Unit, ): LoadStoreCache { val truncatedDeployment = deploymentKey.takeLast(6) val namespace = "amp-exp-$instanceName-$truncatedDeployment-flags" - return LoadStoreCache(namespace, storage, ::decodeFlagFromStorage, ::encodeFlagToStorage) + return LoadStoreCache(namespace, storage, ::decodeFlagFromStorage, ::encodeFlagToStorage, merger) } internal fun decodeVariantFromStorage(storageValue: String): Variant? {