From fcee318b5adc3b4c17e804b9001eda24ccd9edb1 Mon Sep 17 00:00:00 2001 From: Surik Sarkisyan Date: Tue, 4 Jun 2024 14:14:46 +0400 Subject: [PATCH] Added force send properties logic for remote config request (#588) * Added force send properties logic for remote config request * Fixed checks --------- Co-authored-by: Surik --- config/detekt/baseline.xml | 1 + .../sdk/internal/QRemoteConfigManager.kt | 41 +++++++++++++------ .../sdk/internal/QUserPropertiesManager.kt | 22 +++++++++- .../sdk/internal/QonversionInternal.kt | 2 + .../sdk/listeners/QonversionCallback.kt | 5 +++ 5 files changed, 57 insertions(+), 14 deletions(-) diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml index a91d68c2..65ec9b6a 100644 --- a/config/detekt/baseline.xml +++ b/config/detekt/baseline.xml @@ -270,6 +270,7 @@ TooManyFunctions:QProductCenterManager.kt$QProductCenterManager : PurchasesListenerUserStateProvider TooManyFunctions:QRemoteConfigManager.kt$QRemoteConfigManager TooManyFunctions:QRepository.kt$QRepository + TooManyFunctions:QUserPropertiesManager.kt$QUserPropertiesManager : FacebookAttributionListener TooManyFunctions:Qonversion.kt$Qonversion TooManyFunctions:QonversionBillingService.kt$QonversionBillingService : PurchasesUpdatedListenerConnectionListenerBillingService TooManyFunctions:QonversionInternal.kt$QonversionInternal : QonversionLifecycleDelegateAppStateProvider diff --git a/sdk/src/main/java/com/qonversion/android/sdk/internal/QRemoteConfigManager.kt b/sdk/src/main/java/com/qonversion/android/sdk/internal/QRemoteConfigManager.kt index 4d537b65..df770515 100644 --- a/sdk/src/main/java/com/qonversion/android/sdk/internal/QRemoteConfigManager.kt +++ b/sdk/src/main/java/com/qonversion/android/sdk/internal/QRemoteConfigManager.kt @@ -5,6 +5,7 @@ import com.qonversion.android.sdk.dto.QRemoteConfigList import com.qonversion.android.sdk.dto.QonversionError import com.qonversion.android.sdk.internal.provider.UserStateProvider import com.qonversion.android.sdk.internal.services.QRemoteConfigService +import com.qonversion.android.sdk.listeners.QonversionEmptyCallback import com.qonversion.android.sdk.listeners.QonversionExperimentAttachCallback import com.qonversion.android.sdk.listeners.QonversionRemoteConfigCallback import com.qonversion.android.sdk.listeners.QonversionRemoteConfigListCallback @@ -31,6 +32,7 @@ internal class QRemoteConfigManager @Inject constructor( lateinit var userStateProvider: UserStateProvider private var loadingStates = mutableMapOf() private val listRequests = mutableListOf() + lateinit var userPropertiesManager: QUserPropertiesManager fun handlePendingRequests() { loadingStates.filter { it.value.callbacks.isNotEmpty() } @@ -77,14 +79,19 @@ internal class QRemoteConfigManager @Inject constructor( loadingState.isInProgress = true loadingState.loadedConfig = null - remoteConfigService.loadRemoteConfig(contextKey, object : QonversionRemoteConfigCallback { - override fun onSuccess(remoteConfig: QRemoteConfig) { - loadingState.loadedConfig = remoteConfig - fireToCallbacks(contextKey) { onSuccess(remoteConfig) } - } - override fun onError(error: QonversionError) { - fireToCallbacks(contextKey) { onError(error) } + userPropertiesManager.forceSendProperties(object : QonversionEmptyCallback { + override fun onComplete() { + remoteConfigService.loadRemoteConfig(contextKey, object : QonversionRemoteConfigCallback { + override fun onSuccess(remoteConfig: QRemoteConfig) { + loadingState.loadedConfig = remoteConfig + fireToCallbacks(contextKey) { onSuccess(remoteConfig) } + } + + override fun onError(error: QonversionError) { + fireToCallbacks(contextKey) { onError(error) } + } + }) } }) } @@ -106,11 +113,15 @@ internal class QRemoteConfigManager @Inject constructor( return } - remoteConfigService.loadRemoteConfigs( - contextKeys, - includeEmptyContextKey, - getRemoteConfigListCallbackWrapper(callback), - ) + userPropertiesManager.forceSendProperties(object : QonversionEmptyCallback { + override fun onComplete() { + remoteConfigService.loadRemoteConfigs( + contextKeys, + includeEmptyContextKey, + getRemoteConfigListCallbackWrapper(callback), + ) + } + }) } fun loadRemoteConfigList(callback: QonversionRemoteConfigListCallback) { @@ -119,7 +130,11 @@ internal class QRemoteConfigManager @Inject constructor( return } - remoteConfigService.loadRemoteConfigs(getRemoteConfigListCallbackWrapper(callback)) + userPropertiesManager.forceSendProperties(object : QonversionEmptyCallback { + override fun onComplete() { + remoteConfigService.loadRemoteConfigs(getRemoteConfigListCallbackWrapper(callback)) + } + }) } fun attachUserToExperiment(experimentId: String, groupId: String, callback: QonversionExperimentAttachCallback) { diff --git a/sdk/src/main/java/com/qonversion/android/sdk/internal/QUserPropertiesManager.kt b/sdk/src/main/java/com/qonversion/android/sdk/internal/QUserPropertiesManager.kt index 6148b4d1..e78e98dd 100644 --- a/sdk/src/main/java/com/qonversion/android/sdk/internal/QUserPropertiesManager.kt +++ b/sdk/src/main/java/com/qonversion/android/sdk/internal/QUserPropertiesManager.kt @@ -14,6 +14,7 @@ import com.qonversion.android.sdk.internal.logger.Logger import com.qonversion.android.sdk.internal.provider.AppStateProvider import com.qonversion.android.sdk.internal.repository.QRepository import com.qonversion.android.sdk.internal.storage.PropertiesStorage +import com.qonversion.android.sdk.listeners.QonversionEmptyCallback import com.qonversion.android.sdk.listeners.QonversionUserPropertiesCallback import javax.inject.Inject @@ -31,6 +32,7 @@ internal class QUserPropertiesManager @Inject internal constructor( private var isSendingScheduled = false private var retryDelay = PROPERTY_UPLOAD_MIN_DELAY private var retriesCounter = 0 + private var completions = mutableListOf() companion object { private const val LOOPER_THREAD_NAME = "userPropertiesThread" @@ -67,19 +69,27 @@ internal class QUserPropertiesManager @Inject internal constructor( setCustomUserProperty(QUserPropertyKey.FacebookAttribution.userPropertyCode, id) } - fun forceSendProperties() { + public fun forceSendProperties(callback: QonversionEmptyCallback? = null) { if (isRequestInProgress) { + if (callback != null) { + completions.add(callback) + } return } val properties = propertiesStorage.getProperties() if (properties.isNotEmpty()) { + if (callback != null) { + completions.add(callback) + } + isRequestInProgress = true isSendingScheduled = false repository.sendProperties(properties, onSuccess = { result -> + fireCallbacks() result.propertyErrors.forEach { propertyError -> logger.error("Failed to save property ${propertyError.key}: ${propertyError.error}") } @@ -92,6 +102,7 @@ internal class QUserPropertiesManager @Inject internal constructor( propertiesStorage.clear(properties) }, onError = { + fireCallbacks() isRequestInProgress = false if (it.code === QonversionErrorCode.InvalidClientUid) { @@ -108,9 +119,18 @@ internal class QUserPropertiesManager @Inject internal constructor( retryPropertiesRequest() } }) + } else { + callback?.onComplete() } } + private fun fireCallbacks() { + val callbacks = completions.toList() + completions.clear() + + callbacks.forEach { callback -> callback.onComplete() } + } + @VisibleForTesting fun retryPropertiesRequest() { retriesCounter++ diff --git a/sdk/src/main/java/com/qonversion/android/sdk/internal/QonversionInternal.kt b/sdk/src/main/java/com/qonversion/android/sdk/internal/QonversionInternal.kt index 35f0e7e6..dd74687c 100644 --- a/sdk/src/main/java/com/qonversion/android/sdk/internal/QonversionInternal.kt +++ b/sdk/src/main/java/com/qonversion/android/sdk/internal/QonversionInternal.kt @@ -104,6 +104,8 @@ internal class QonversionInternal( userPropertiesManager.productCenterManager = productCenterManager userPropertiesManager.sendFacebookAttribution() + remoteConfigManager.userPropertiesManager = userPropertiesManager + val lifecycleHandler = AppLifecycleHandler(this) postToMainThread { ProcessLifecycleOwner.get().lifecycle.addObserver(lifecycleHandler) } diff --git a/sdk/src/main/java/com/qonversion/android/sdk/listeners/QonversionCallback.kt b/sdk/src/main/java/com/qonversion/android/sdk/listeners/QonversionCallback.kt index 48deeeca..6ec342b3 100644 --- a/sdk/src/main/java/com/qonversion/android/sdk/listeners/QonversionCallback.kt +++ b/sdk/src/main/java/com/qonversion/android/sdk/listeners/QonversionCallback.kt @@ -70,3 +70,8 @@ interface QonversionUserPropertiesCallback { fun onSuccess(userProperties: QUserProperties) fun onError(error: QonversionError) } + +interface QonversionEmptyCallback { + + fun onComplete() +}