From e6bfb3af85b51f74929c5819372e10fd3adc0283 Mon Sep 17 00:00:00 2001 From: Rodrigo Gomez Palacio Date: Thu, 24 Oct 2024 15:23:19 -0500 Subject: [PATCH 1/9] Encapsulate `rywToken` & `rywDelay` in `RywData` data class object Motivation: we need to keep the two values together in order to know how much to delay by (based on what rywToken is newest) --- .../src/main/java/com/onesignal/common/consistency/RywData.kt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/RywData.kt diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/RywData.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/RywData.kt new file mode 100644 index 000000000..4fcf7b3be --- /dev/null +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/RywData.kt @@ -0,0 +1,3 @@ +package com.onesignal.common.consistency + +data class RywData(val rywToken: String?, val rywDelay: Long?) From 251976bddb3d3e487c591ceead8247a60f857453 Mon Sep 17 00:00:00 2001 From: Rodrigo Gomez Palacio Date: Thu, 24 Oct 2024 15:25:34 -0500 Subject: [PATCH 2/9] Nit: rename method for clarity Motivation: it's unclear from the previous method name that we are expecting something to be returned. --- .../common/consistency/impl/ConsistencyManager.kt | 2 +- .../common/consistency/models/IConsistencyManager.kt | 2 +- .../common/consistency/ConsistencyManagerTests.kt | 8 ++++---- .../inAppMessages/internal/InAppMessagesManager.kt | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/impl/ConsistencyManager.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/impl/ConsistencyManager.kt index 139c06e3b..c5f27b27b 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/impl/ConsistencyManager.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/impl/ConsistencyManager.kt @@ -44,7 +44,7 @@ class ConsistencyManager : IConsistencyManager { /** * Register a condition with its corresponding deferred action. Returns a deferred condition. */ - override suspend fun registerCondition(condition: ICondition): CompletableDeferred { + override suspend fun getRywDataFromAwaitableCondition(condition: ICondition): CompletableDeferred { mutex.withLock { val deferred = CompletableDeferred() val pair = Pair(condition, deferred) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/IConsistencyManager.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/IConsistencyManager.kt index d1bba5312..627846206 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/IConsistencyManager.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/IConsistencyManager.kt @@ -22,7 +22,7 @@ interface IConsistencyManager { * condition: ICondition - the condition to be registered * Returns: CompletableDeferred - a deferred action that completes when the condition is met */ - suspend fun registerCondition(condition: ICondition): CompletableDeferred + suspend fun getRywDataFromAwaitableCondition(condition: ICondition): CompletableDeferred /** * Resolve all conditions with a specific ID diff --git a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/common/consistency/ConsistencyManagerTests.kt b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/common/consistency/ConsistencyManagerTests.kt index f92174e0b..bac47c727 100644 --- a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/common/consistency/ConsistencyManagerTests.kt +++ b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/common/consistency/ConsistencyManagerTests.kt @@ -25,7 +25,7 @@ class ConsistencyManagerTests : FunSpec({ consistencyManager.setRywToken(id, key, value) val condition = TestMetCondition(mapOf(id to mapOf(key to value))) - val deferred = consistencyManager.registerCondition(condition) + val deferred = consistencyManager.getRywDataFromAwaitableCondition(condition) val result = deferred.await() result shouldBe value @@ -43,7 +43,7 @@ class ConsistencyManagerTests : FunSpec({ consistencyManager.setRywToken(id, key, value) val condition = TestMetCondition(mapOf(id to mapOf(key to value))) - val deferred = consistencyManager.registerCondition(condition) + val deferred = consistencyManager.getRywDataFromAwaitableCondition(condition) deferred.await() deferred.isCompleted shouldBe true @@ -53,7 +53,7 @@ class ConsistencyManagerTests : FunSpec({ test("registerCondition does not complete when condition is not met") { runTest { val condition = TestUnmetCondition() - val deferred = consistencyManager.registerCondition(condition) + val deferred = consistencyManager.getRywDataFromAwaitableCondition(condition) consistencyManager.setRywToken("id", IamFetchRywTokenKey.USER, "123") deferred.isCompleted shouldBe false @@ -63,7 +63,7 @@ class ConsistencyManagerTests : FunSpec({ test("resolveConditionsWithID resolves conditions based on ID") { runTest { val condition = TestUnmetCondition() - val deferred = consistencyManager.registerCondition(condition) + val deferred = consistencyManager.getRywDataFromAwaitableCondition(condition) consistencyManager.resolveConditionsWithID(TestUnmetCondition.ID) deferred.await() diff --git a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt index 0bf5ff8c7..428eef21b 100644 --- a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt +++ b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt @@ -164,7 +164,7 @@ internal class InAppMessagesManager( // attempt to fetch messages from the backend (if we have the pre-requisite data already) val onesignalId = _userManager.onesignalId val updateConditionDeferred = - _consistencyManager.registerCondition(IamFetchReadyCondition(onesignalId)) + _consistencyManager.getRywDataFromAwaitableCondition(IamFetchReadyCondition(onesignalId)) val rywToken = updateConditionDeferred.await() if (rywToken != null) { fetchMessages(rywToken) @@ -241,7 +241,7 @@ internal class InAppMessagesManager( suspendifyOnThread { val onesignalId = _userManager.onesignalId val iamFetchCondition = - _consistencyManager.registerCondition(IamFetchReadyCondition(onesignalId)) + _consistencyManager.getRywDataFromAwaitableCondition(IamFetchReadyCondition(onesignalId)) val rywToken = iamFetchCondition.await() if (rywToken != null) { From 8b79aace7dfb9106a811c58a8e8b62b32ffb3a27 Mon Sep 17 00:00:00 2001 From: Rodrigo Gomez Palacio Date: Thu, 24 Oct 2024 16:26:17 -0500 Subject: [PATCH 3/9] Delay the IAM fetch by `rywDelay` w/ fallback Motivation: make use of the new object to pull out the `rywDelay` value & delay by that amount. By doing so we help minimize the number of retries that will hit the backend. --- .../internal/backend/impl/InAppBackendService.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/backend/impl/InAppBackendService.kt b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/backend/impl/InAppBackendService.kt index f541f9b32..93a99ad87 100644 --- a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/backend/impl/InAppBackendService.kt +++ b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/backend/impl/InAppBackendService.kt @@ -14,6 +14,8 @@ import com.onesignal.inAppMessages.internal.hydrators.InAppHydrator import kotlinx.coroutines.delay import org.json.JSONObject +private const val DEFAULT_RYW_DELAY_MS = 500L + internal class InAppBackendService( private val _httpClient: IHttpClient, private val _deviceService: IDeviceService, @@ -27,6 +29,9 @@ internal class InAppBackendService( rywToken: String?, sessionDurationProvider: () -> Long, ): List? { + val rywDelay = rywData.rywDelay ?: DEFAULT_RYW_DELAY_MS + delay(rywDelay) // Delay by the specified amount + val baseUrl = "apps/$appId/subscriptions/$subscriptionId/iams" return attemptFetchWithRetries(baseUrl, rywToken, sessionDurationProvider) } From bb4a0b794e19a85785db3e5b5495fd2152ca8fce Mon Sep 17 00:00:00 2001 From: Rodrigo Gomez Palacio Date: Thu, 24 Oct 2024 16:23:55 -0500 Subject: [PATCH 4/9] Use `RywData` everywhere we were previously using `String` (`rywToken`) Motivation: update all usages of `rywToken` to now make use of the new `RywData` object. In `ConsistencyManager` we also renamed the method `setRywToken` to `setRywData` --- .../consistency/IamFetchReadyCondition.kt | 12 ++++--- .../consistency/impl/ConsistencyManager.kt | 19 ++++++----- .../common/consistency/models/ICondition.kt | 6 ++-- .../consistency/models/IConsistencyManager.kt | 7 ++-- .../backend/ISubscriptionBackendService.kt | 5 +-- .../internal/backend/IUserBackendService.kt | 3 +- .../impl/SubscriptionBackendService.kt | 30 ++++++++++++----- .../backend/impl/UserBackendService.kt | 19 +++++++---- .../SubscriptionOperationExecutor.kt | 12 +++---- .../executors/UpdateUserOperationExecutor.kt | 6 ++-- .../consistency/ConsistencyManagerTests.kt | 33 +++++++++++-------- .../SubscriptionBackendServiceTests.kt | 3 +- .../SubscriptionOperationExecutorTests.kt | 15 +++++---- .../UpdateUserOperationExecutorTests.kt | 19 ++++++----- .../internal/InAppMessagesManager.kt | 11 ++++--- .../internal/backend/IInAppBackendService.kt | 3 +- .../backend/impl/InAppBackendService.kt | 9 ++--- .../backend/InAppBackendServiceTests.kt | 9 ++--- 18 files changed, 132 insertions(+), 89 deletions(-) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/IamFetchReadyCondition.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/IamFetchReadyCondition.kt index d43e3c989..4a07166e1 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/IamFetchReadyCondition.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/IamFetchReadyCondition.kt @@ -20,7 +20,7 @@ class IamFetchReadyCondition( override val id: String get() = ID - override fun isMet(indexedTokens: Map>): Boolean { + override fun isMet(indexedTokens: Map>): Boolean { val tokenMap = indexedTokens[key] ?: return false val userUpdateTokenSet = tokenMap[IamFetchRywTokenKey.USER] != null @@ -33,9 +33,13 @@ class IamFetchReadyCondition( return userUpdateTokenSet } - override fun getNewestToken(indexedTokens: Map>): String? { + override fun getNewestToken(indexedTokens: Map>): RywData? { val tokenMap = indexedTokens[key] ?: return null - // maxOrNull compares lexicographically - return listOfNotNull(tokenMap[IamFetchRywTokenKey.USER], tokenMap[IamFetchRywTokenKey.SUBSCRIPTION]).maxOrNull() + + // Collect non-null RywData objects and find the one with the largest rywToken lexicographically + return listOfNotNull( + tokenMap[IamFetchRywTokenKey.USER], + tokenMap[IamFetchRywTokenKey.SUBSCRIPTION], + ).maxByOrNull { it.rywToken ?: "" } } } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/impl/ConsistencyManager.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/impl/ConsistencyManager.kt index c5f27b27b..f21e62d77 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/impl/ConsistencyManager.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/impl/ConsistencyManager.kt @@ -1,5 +1,6 @@ package com.onesignal.common.consistency.impl +import com.onesignal.common.consistency.RywData import com.onesignal.common.consistency.models.ICondition import com.onesignal.common.consistency.models.IConsistencyKeyEnum import com.onesignal.common.consistency.models.IConsistencyManager @@ -18,8 +19,8 @@ import kotlinx.coroutines.sync.withLock */ class ConsistencyManager : IConsistencyManager { private val mutex = Mutex() - private val indexedTokens: MutableMap> = mutableMapOf() - private val conditions: MutableList>> = + private val indexedTokens: MutableMap> = mutableMapOf() + private val conditions: MutableList>> = mutableListOf() /** @@ -29,10 +30,10 @@ class ConsistencyManager : IConsistencyManager { * key: K - corresponds to the operation for which we have a read-your-write token * value: String? - the token (read-your-write token) */ - override suspend fun setRywToken( + override suspend fun setRywData( id: String, key: IConsistencyKeyEnum, - value: String, + value: RywData, ) { mutex.withLock { val rywTokens = indexedTokens.getOrPut(id) { mutableMapOf() } @@ -46,7 +47,7 @@ class ConsistencyManager : IConsistencyManager { */ override suspend fun getRywDataFromAwaitableCondition(condition: ICondition): CompletableDeferred { mutex.withLock { - val deferred = CompletableDeferred() + val deferred = CompletableDeferred() val pair = Pair(condition, deferred) conditions.add(pair) checkConditionsAndComplete() @@ -55,7 +56,7 @@ class ConsistencyManager : IConsistencyManager { } override suspend fun resolveConditionsWithID(id: String) { - val completedConditions = mutableListOf>>() + val completedConditions = mutableListOf>>() for ((condition, deferred) in conditions) { if (condition.id == id) { @@ -74,13 +75,13 @@ class ConsistencyManager : IConsistencyManager { * IMPORTANT: calling code should be protected by mutex to avoid potential inconsistencies */ private fun checkConditionsAndComplete() { - val completedConditions = mutableListOf>>() + val completedConditions = mutableListOf>>() for ((condition, deferred) in conditions) { if (condition.isMet(indexedTokens)) { - val newestToken = condition.getNewestToken(indexedTokens) + val rywDataForNewestToken = condition.getNewestToken(indexedTokens) if (!deferred.isCompleted) { - deferred.complete(newestToken) + deferred.complete(rywDataForNewestToken) } completedConditions.add(Pair(condition, deferred)) } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/ICondition.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/ICondition.kt index fbb97d23b..988d58bb6 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/ICondition.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/ICondition.kt @@ -1,5 +1,7 @@ package com.onesignal.common.consistency.models +import com.onesignal.common.consistency.RywData + interface ICondition { /** * Every implementation should define a unique ID & make available via a companion object for @@ -11,11 +13,11 @@ interface ICondition { * Define a condition that "unblocks" execution * e.g. we have token (A && B) || A */ - fun isMet(indexedTokens: Map>): Boolean + fun isMet(indexedTokens: Map>): Boolean /** * Used to process tokens according to their format & return the newest token. * e.g. numeric strings would be compared differently from JWT tokens */ - fun getNewestToken(indexedTokens: Map>): String? + fun getNewestToken(indexedTokens: Map>): RywData? } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/IConsistencyManager.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/IConsistencyManager.kt index 627846206..bdcbf38ba 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/IConsistencyManager.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/IConsistencyManager.kt @@ -1,5 +1,6 @@ package com.onesignal.common.consistency.models +import com.onesignal.common.consistency.RywData import kotlinx.coroutines.CompletableDeferred interface IConsistencyManager { @@ -10,10 +11,10 @@ interface IConsistencyManager { * key: IConsistencyKeyEnum - corresponds to the operation for which we have a read-your-write token * value: String? - the read-your-write token */ - suspend fun setRywToken( + suspend fun setRywData( id: String, key: IConsistencyKeyEnum, - value: String, + value: RywData, ) /** @@ -22,7 +23,7 @@ interface IConsistencyManager { * condition: ICondition - the condition to be registered * Returns: CompletableDeferred - a deferred action that completes when the condition is met */ - suspend fun getRywDataFromAwaitableCondition(condition: ICondition): CompletableDeferred + suspend fun getRywDataFromAwaitableCondition(condition: ICondition): CompletableDeferred /** * Resolve all conditions with a specific ID diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/ISubscriptionBackendService.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/ISubscriptionBackendService.kt index 133f298e7..65ade278c 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/ISubscriptionBackendService.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/ISubscriptionBackendService.kt @@ -1,5 +1,6 @@ package com.onesignal.user.internal.backend +import com.onesignal.common.consistency.RywData import com.onesignal.common.exceptions.BackendException interface ISubscriptionBackendService { @@ -21,7 +22,7 @@ interface ISubscriptionBackendService { aliasLabel: String, aliasValue: String, subscription: SubscriptionObject, - ): Pair? + ): Pair? /** * Update an existing subscription with the properties provided. @@ -34,7 +35,7 @@ interface ISubscriptionBackendService { appId: String, subscriptionId: String, subscription: SubscriptionObject, - ): String? + ): RywData /** * Delete an existing subscription. diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/IUserBackendService.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/IUserBackendService.kt index 62837fb26..bc450c16f 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/IUserBackendService.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/IUserBackendService.kt @@ -1,5 +1,6 @@ package com.onesignal.user.internal.backend +import com.onesignal.common.consistency.RywData import com.onesignal.common.exceptions.BackendException interface IUserBackendService { @@ -47,7 +48,7 @@ interface IUserBackendService { properties: PropertiesObject, refreshDeviceMetadata: Boolean, propertyiesDelta: PropertiesDeltasObject, - ): String? + ): RywData /** * Retrieve a user from the backend. diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/SubscriptionBackendService.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/SubscriptionBackendService.kt index 25d0e0a3e..181678058 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/SubscriptionBackendService.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/SubscriptionBackendService.kt @@ -1,5 +1,6 @@ package com.onesignal.user.internal.backend.impl +import com.onesignal.common.consistency.RywData import com.onesignal.common.exceptions.BackendException import com.onesignal.common.safeJSONObject import com.onesignal.common.toMap @@ -16,7 +17,7 @@ internal class SubscriptionBackendService( aliasLabel: String, aliasValue: String, subscription: SubscriptionObject, - ): Pair? { + ): Pair? { val jsonSubscription = JSONConverter.convertToJSON(subscription) jsonSubscription.remove("id") val requestJSON = JSONObject().put("subscription", jsonSubscription) @@ -38,14 +39,21 @@ internal class SubscriptionBackendService( rywToken = responseJSON.getString("ryw_token") } - return Pair(subscriptionJSON.getString("id"), rywToken) + var rywDelay: Long? = null + if (responseJSON.has("ryw_delay")) { + rywDelay = responseJSON.getLong("ryw_delay") + } + + var rywData = RywData(rywToken, rywDelay) + + return Pair(subscriptionJSON.getString("id"), rywData) } override suspend fun updateSubscription( appId: String, subscriptionId: String, subscription: SubscriptionObject, - ): String? { + ): RywData { val requestJSON = JSONObject() .put("subscription", JSONConverter.convertToJSON(subscription)) @@ -56,12 +64,18 @@ internal class SubscriptionBackendService( throw BackendException(response.statusCode, response.payload, response.retryAfterSeconds) } - val responseBody = JSONObject(response.payload) - return if (responseBody.has("ryw_token")) { - responseBody.getString("ryw_token") - } else { - null + val responseJSON = JSONObject(response.payload) + var rywToken: String? = null + if (responseJSON.has("ryw_token")) { + rywToken = responseJSON.getString("ryw_token") + } + + var rywDelay: Long? = null + if (responseJSON.has("ryw_delay")) { + rywDelay = responseJSON.getLong("ryw_delay") } + + return RywData(rywToken, rywDelay) } override suspend fun deleteSubscription( diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/UserBackendService.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/UserBackendService.kt index 996f637e7..333082541 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/UserBackendService.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/UserBackendService.kt @@ -1,5 +1,6 @@ package com.onesignal.user.internal.backend.impl +import com.onesignal.common.consistency.RywData import com.onesignal.common.exceptions.BackendException import com.onesignal.common.putMap import com.onesignal.core.internal.http.IHttpClient @@ -52,7 +53,7 @@ internal class UserBackendService( properties: PropertiesObject, refreshDeviceMetadata: Boolean, propertyiesDelta: PropertiesDeltasObject, - ): String? { + ): RywData { val jsonObject = JSONObject() .put("refresh_device_metadata", refreshDeviceMetadata) @@ -71,12 +72,18 @@ internal class UserBackendService( throw BackendException(response.statusCode, response.payload, response.retryAfterSeconds) } - val responseBody = JSONObject(response.payload) - return if (responseBody.has("ryw_token")) { - responseBody.getString("ryw_token") - } else { - null + val responseJSON = JSONObject(response.payload) + var rywToken: String? = null + if (responseJSON.has("ryw_token")) { + rywToken = responseJSON.getString("ryw_token") } + + var rywDelay: Long? = null + if (responseJSON.has("ryw_delay")) { + rywDelay = responseJSON.getLong("ryw_delay") + } + + return RywData(rywToken, rywDelay) } override suspend fun getUser( diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/SubscriptionOperationExecutor.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/SubscriptionOperationExecutor.kt index 1622d55f1..18e44d128 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/SubscriptionOperationExecutor.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/SubscriptionOperationExecutor.kt @@ -114,10 +114,10 @@ internal class SubscriptionOperationExecutor( ) ?: return ExecutionResponse(ExecutionResult.SUCCESS) val backendSubscriptionId = result.first - val rywToken = result.second + val rywData = result.second - if (rywToken != null) { - _consistencyManager.setRywToken(createOperation.onesignalId, IamFetchRywTokenKey.SUBSCRIPTION, rywToken) + if (rywData.rywToken != null) { + _consistencyManager.setRywData(createOperation.onesignalId, IamFetchRywTokenKey.SUBSCRIPTION, rywData) } else { _consistencyManager.resolveConditionsWithID(IamFetchReadyCondition.ID) } @@ -188,10 +188,10 @@ internal class SubscriptionOperationExecutor( AndroidUtils.getAppVersion(_applicationService.appContext), ) - val rywToken = _subscriptionBackend.updateSubscription(lastOperation.appId, lastOperation.subscriptionId, subscription) + val rywData = _subscriptionBackend.updateSubscription(lastOperation.appId, lastOperation.subscriptionId, subscription) - if (rywToken != null) { - _consistencyManager.setRywToken(startingOperation.onesignalId, IamFetchRywTokenKey.SUBSCRIPTION, rywToken) + if (rywData.rywToken != null) { + _consistencyManager.setRywData(startingOperation.onesignalId, IamFetchRywTokenKey.SUBSCRIPTION, rywData) } else { _consistencyManager.resolveConditionsWithID(IamFetchReadyCondition.ID) } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/UpdateUserOperationExecutor.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/UpdateUserOperationExecutor.kt index 0f28ae61d..91c6f9460 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/UpdateUserOperationExecutor.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/UpdateUserOperationExecutor.kt @@ -138,7 +138,7 @@ internal class UpdateUserOperationExecutor( if (appId != null && onesignalId != null) { try { - val rywToken = + val rywData = _userBackend.updateUser( appId, IdentityConstants.ONESIGNAL_ID, @@ -148,8 +148,8 @@ internal class UpdateUserOperationExecutor( deltasObject, ) - if (rywToken != null) { - _consistencyManager.setRywToken(onesignalId, IamFetchRywTokenKey.USER, rywToken) + if (rywData.rywToken != null) { + _consistencyManager.setRywData(onesignalId, IamFetchRywTokenKey.USER, rywData) } else { _consistencyManager.resolveConditionsWithID(IamFetchReadyCondition.ID) } diff --git a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/common/consistency/ConsistencyManagerTests.kt b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/common/consistency/ConsistencyManagerTests.kt index bac47c727..9627eb76a 100644 --- a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/common/consistency/ConsistencyManagerTests.kt +++ b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/common/consistency/ConsistencyManagerTests.kt @@ -1,6 +1,7 @@ -package com.onesignal.common.consistency.impl +package com.onesignal.common.consistency import com.onesignal.common.consistency.enums.IamFetchRywTokenKey +import com.onesignal.common.consistency.impl.ConsistencyManager import com.onesignal.common.consistency.models.ICondition import com.onesignal.common.consistency.models.IConsistencyKeyEnum import io.kotest.core.spec.style.FunSpec @@ -20,15 +21,17 @@ class ConsistencyManagerTests : FunSpec({ // Given val id = "test_id" val key = IamFetchRywTokenKey.USER - val value = "123" + val token = "123" + val delay = 500L + val rywData = RywData(token, delay) - consistencyManager.setRywToken(id, key, value) + consistencyManager.setRywData(id, key, rywData) - val condition = TestMetCondition(mapOf(id to mapOf(key to value))) + val condition = TestMetCondition(mapOf(id to mapOf(key to rywData))) val deferred = consistencyManager.getRywDataFromAwaitableCondition(condition) val result = deferred.await() - result shouldBe value + result shouldBe rywData } } @@ -37,12 +40,14 @@ class ConsistencyManagerTests : FunSpec({ // Given val id = "test_id" val key = IamFetchRywTokenKey.USER - val value = "123" + val token = "123" + val delay = 500L + val rywData = RywData(token, delay) // Set a token to meet the condition - consistencyManager.setRywToken(id, key, value) + consistencyManager.setRywData(id, key, rywData) - val condition = TestMetCondition(mapOf(id to mapOf(key to value))) + val condition = TestMetCondition(mapOf(id to mapOf(key to rywData))) val deferred = consistencyManager.getRywDataFromAwaitableCondition(condition) deferred.await() @@ -55,7 +60,7 @@ class ConsistencyManagerTests : FunSpec({ val condition = TestUnmetCondition() val deferred = consistencyManager.getRywDataFromAwaitableCondition(condition) - consistencyManager.setRywToken("id", IamFetchRywTokenKey.USER, "123") + consistencyManager.setRywData("id", IamFetchRywTokenKey.USER, RywData("123", 500L)) deferred.isCompleted shouldBe false } } @@ -80,18 +85,18 @@ class ConsistencyManagerTests : FunSpec({ override val id: String get() = ID - override fun isMet(indexedTokens: Map>): Boolean { + override fun isMet(indexedTokens: Map>): Boolean { return false // Always returns false to simulate an unmet condition } - override fun getNewestToken(indexedTokens: Map>): String? { + override fun getNewestToken(indexedTokens: Map>): RywData? { return null } } // Mock implementation of ICondition for cases where the condition is met private class TestMetCondition( - private val expectedRywTokens: Map>, + private val expectedRywTokens: Map>, ) : ICondition { companion object { const val ID = "TestMetCondition" @@ -100,11 +105,11 @@ class ConsistencyManagerTests : FunSpec({ override val id: String get() = ID - override fun isMet(indexedTokens: Map>): Boolean { + override fun isMet(indexedTokens: Map>): Boolean { return indexedTokens == expectedRywTokens } - override fun getNewestToken(indexedTokens: Map>): String? { + override fun getNewestToken(indexedTokens: Map>): RywData? { return expectedRywTokens.values.firstOrNull()?.values?.firstOrNull() } } diff --git a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/backend/SubscriptionBackendServiceTests.kt b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/backend/SubscriptionBackendServiceTests.kt index c228a5c5c..cabe340dd 100644 --- a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/backend/SubscriptionBackendServiceTests.kt +++ b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/backend/SubscriptionBackendServiceTests.kt @@ -1,5 +1,6 @@ package com.onesignal.user.internal.backend +import com.onesignal.common.consistency.RywData import com.onesignal.common.exceptions.BackendException import com.onesignal.core.internal.http.HttpResponse import com.onesignal.core.internal.http.IHttpClient @@ -42,7 +43,7 @@ class SubscriptionBackendServiceTests : FunSpec({ val response = subscriptionBackendService.createSubscription("appId", aliasLabel, aliasValue, subscription) // Then - response shouldBe Pair("subscriptionId", null) + response shouldBe Pair("subscriptionId", RywData(null, null)) coVerify { spyHttpClient.post( "apps/appId/users/by/$aliasLabel/$aliasValue/subscriptions", diff --git a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/operations/SubscriptionOperationExecutorTests.kt b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/operations/SubscriptionOperationExecutorTests.kt index 87d5f4a0b..9ed8cd2a0 100644 --- a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/operations/SubscriptionOperationExecutorTests.kt +++ b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/operations/SubscriptionOperationExecutorTests.kt @@ -1,6 +1,7 @@ package com.onesignal.user.internal.operations import br.com.colman.kotest.android.extensions.robolectric.RobolectricTest +import com.onesignal.common.consistency.RywData import com.onesignal.common.consistency.enums.IamFetchRywTokenKey import com.onesignal.common.consistency.models.IConsistencyManager import com.onesignal.common.exceptions.BackendException @@ -36,19 +37,19 @@ class SubscriptionOperationExecutorTests : val remoteOneSignalId = "remote-onesignalId" val localSubscriptionId = "local-subscriptionId1" val remoteSubscriptionId = "remote-subscriptionId1" - val rywToken = "1" + val rywData = RywData("1", 500L) val mockConsistencyManager = mockk() beforeTest { clearMocks(mockConsistencyManager) - coEvery { mockConsistencyManager.setRywToken(any(), any(), any()) } just runs + coEvery { mockConsistencyManager.setRywData(any(), any(), any()) } just runs } test("create subscription successfully creates subscription") { // Given val mockSubscriptionBackendService = mockk() coEvery { mockSubscriptionBackendService.createSubscription(any(), any(), any(), any()) } returns - Pair(remoteSubscriptionId, rywToken) + Pair(remoteSubscriptionId, rywData) val mockSubscriptionsModelStore = mockk() val subscriptionModel1 = SubscriptionModel() @@ -302,7 +303,7 @@ class SubscriptionOperationExecutorTests : // Given val mockSubscriptionBackendService = mockk() coEvery { mockSubscriptionBackendService.createSubscription(any(), any(), any(), any()) } returns - Pair(remoteSubscriptionId, rywToken) + Pair(remoteSubscriptionId, rywData) val mockSubscriptionsModelStore = mockk() val subscriptionModel1 = SubscriptionModel() @@ -369,7 +370,7 @@ class SubscriptionOperationExecutorTests : test("update subscription successfully updates subscription") { // Given val mockSubscriptionBackendService = mockk() - coEvery { mockSubscriptionBackendService.updateSubscription(any(), any(), any()) } returns rywToken + coEvery { mockSubscriptionBackendService.updateSubscription(any(), any(), any()) } returns rywData val mockSubscriptionsModelStore = mockk() val subscriptionModel1 = @@ -723,7 +724,7 @@ class SubscriptionOperationExecutorTests : val mockSubscriptionBackendService = mockk() coEvery { mockSubscriptionBackendService.updateSubscription(any(), any(), any()) - } returns rywToken + } returns rywData val mockSubscriptionsModelStore = mockk() val subscriptionModel1 = @@ -764,7 +765,7 @@ class SubscriptionOperationExecutorTests : // Then coVerify(exactly = 1) { - mockConsistencyManager.setRywToken(remoteOneSignalId, IamFetchRywTokenKey.SUBSCRIPTION, rywToken) + mockConsistencyManager.setRywData(remoteOneSignalId, IamFetchRywTokenKey.SUBSCRIPTION, rywData) } } }) diff --git a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/operations/UpdateUserOperationExecutorTests.kt b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/operations/UpdateUserOperationExecutorTests.kt index 4c511e375..de2e148ff 100644 --- a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/operations/UpdateUserOperationExecutorTests.kt +++ b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/operations/UpdateUserOperationExecutorTests.kt @@ -1,5 +1,6 @@ package com.onesignal.user.internal.operations +import com.onesignal.common.consistency.RywData import com.onesignal.common.consistency.enums.IamFetchRywTokenKey import com.onesignal.common.consistency.models.IConsistencyManager import com.onesignal.common.exceptions.BackendException @@ -29,18 +30,18 @@ class UpdateUserOperationExecutorTests : val appId = "appId" val localOneSignalId = "local-onesignalId" val remoteOneSignalId = "remote-onesignalId" - val rywToken = "1" + val rywData = RywData("1", 500L) val mockConsistencyManager = mockk() beforeTest { clearMocks(mockConsistencyManager) - coEvery { mockConsistencyManager.setRywToken(any(), any(), any()) } just runs + coEvery { mockConsistencyManager.setRywData(any(), any(), any()) } just runs } test("update user single operation is successful") { // Given val mockUserBackendService = mockk() - coEvery { mockUserBackendService.updateUser(any(), any(), any(), any(), any(), any()) } returns rywToken + coEvery { mockUserBackendService.updateUser(any(), any(), any(), any(), any(), any()) } returns rywData // Given val mockIdentityModelStore = MockHelper.identityModelStore() @@ -80,7 +81,7 @@ class UpdateUserOperationExecutorTests : test("update user multiple property operations are successful") { // Given val mockUserBackendService = mockk() - coEvery { mockUserBackendService.updateUser(any(), any(), any(), any(), any(), any()) } returns rywToken + coEvery { mockUserBackendService.updateUser(any(), any(), any(), any(), any(), any()) } returns rywData // Given val mockIdentityModelStore = MockHelper.identityModelStore() @@ -142,7 +143,7 @@ class UpdateUserOperationExecutorTests : test("update user single property delta operations is successful") { // Given val mockUserBackendService = mockk() - coEvery { mockUserBackendService.updateUser(any(), any(), any(), any(), any(), any()) } returns rywToken + coEvery { mockUserBackendService.updateUser(any(), any(), any(), any(), any(), any()) } returns rywData // Given val mockIdentityModelStore = MockHelper.identityModelStore() @@ -187,7 +188,7 @@ class UpdateUserOperationExecutorTests : test("update user multiple property delta operations are successful") { // Given val mockUserBackendService = mockk() - coEvery { mockUserBackendService.updateUser(any(), any(), any(), any(), any(), any()) } returns rywToken + coEvery { mockUserBackendService.updateUser(any(), any(), any(), any(), any(), any()) } returns rywData // Given val mockIdentityModelStore = MockHelper.identityModelStore() @@ -252,7 +253,7 @@ class UpdateUserOperationExecutorTests : test("update user with both property and property delta operations are successful") { // Given val mockUserBackendService = mockk() - coEvery { mockUserBackendService.updateUser(any(), any(), any(), any(), any(), any()) } returns rywToken + coEvery { mockUserBackendService.updateUser(any(), any(), any(), any(), any(), any()) } returns rywData // Given val mockIdentityModelStore = MockHelper.identityModelStore() @@ -364,7 +365,7 @@ class UpdateUserOperationExecutorTests : val mockUserBackendService = mockk() coEvery { mockUserBackendService.updateUser(any(), any(), any(), any(), any(), any()) - } returns rywToken + } returns rywData val mockIdentityModelStore = MockHelper.identityModelStore() val mockPropertiesModelStore = MockHelper.propertiesModelStore() @@ -390,7 +391,7 @@ class UpdateUserOperationExecutorTests : // Then coVerify(exactly = 1) { - mockConsistencyManager.setRywToken(remoteOneSignalId, IamFetchRywTokenKey.USER, rywToken) + mockConsistencyManager.setRywData(remoteOneSignalId, IamFetchRywTokenKey.USER, rywData) } } }) diff --git a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt index 428eef21b..f1743d371 100644 --- a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt +++ b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt @@ -5,6 +5,7 @@ import com.onesignal.common.AndroidUtils import com.onesignal.common.IDManager import com.onesignal.common.JSONUtils import com.onesignal.common.consistency.IamFetchReadyCondition +import com.onesignal.common.consistency.RywData import com.onesignal.common.consistency.models.IConsistencyManager import com.onesignal.common.events.EventProducer import com.onesignal.common.exceptions.BackendException @@ -242,16 +243,16 @@ internal class InAppMessagesManager( val onesignalId = _userManager.onesignalId val iamFetchCondition = _consistencyManager.getRywDataFromAwaitableCondition(IamFetchReadyCondition(onesignalId)) - val rywToken = iamFetchCondition.await() + val rywData = iamFetchCondition.await() - if (rywToken != null) { - fetchMessages(rywToken) + if (rywData != null) { + fetchMessages(rywData) } } } // called when a new push subscription is added, or the app id is updated, or a new session starts - private suspend fun fetchMessages(rywToken: String?) { + private suspend fun fetchMessages(rywData: RywData) { // We only want to fetch IAMs if we know the app is in the // foreground, as we don't want to do this for background // events (such as push received), wasting resources for @@ -278,7 +279,7 @@ internal class InAppMessagesManager( // lambda so that it is updated on each potential retry val sessionDurationProvider = { _time.currentTimeMillis - _sessionService.startTime } - val newMessages = _backend.listInAppMessages(appId, subscriptionId, rywToken, sessionDurationProvider) + val newMessages = _backend.listInAppMessages(appId, subscriptionId, rywData, sessionDurationProvider) if (newMessages != null) { this.messages = newMessages as MutableList diff --git a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/backend/IInAppBackendService.kt b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/backend/IInAppBackendService.kt index 85db9f689..6755b6eb5 100644 --- a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/backend/IInAppBackendService.kt +++ b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/backend/IInAppBackendService.kt @@ -1,5 +1,6 @@ package com.onesignal.inAppMessages.internal.backend +import com.onesignal.common.consistency.RywData import com.onesignal.common.exceptions.BackendException import com.onesignal.inAppMessages.internal.InAppMessage import com.onesignal.inAppMessages.internal.InAppMessageContent @@ -21,7 +22,7 @@ internal interface IInAppBackendService { suspend fun listInAppMessages( appId: String, subscriptionId: String, - rywToken: String?, + rywData: RywData, sessionDurationProvider: () -> Long, ): List? diff --git a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/backend/impl/InAppBackendService.kt b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/backend/impl/InAppBackendService.kt index 93a99ad87..79d9a7609 100644 --- a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/backend/impl/InAppBackendService.kt +++ b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/backend/impl/InAppBackendService.kt @@ -1,6 +1,7 @@ package com.onesignal.inAppMessages.internal.backend.impl import com.onesignal.common.NetworkUtils +import com.onesignal.common.consistency.RywData import com.onesignal.common.exceptions.BackendException import com.onesignal.core.internal.device.IDeviceService import com.onesignal.core.internal.http.IHttpClient @@ -26,14 +27,14 @@ internal class InAppBackendService( override suspend fun listInAppMessages( appId: String, subscriptionId: String, - rywToken: String?, + rywData: RywData, sessionDurationProvider: () -> Long, ): List? { val rywDelay = rywData.rywDelay ?: DEFAULT_RYW_DELAY_MS delay(rywDelay) // Delay by the specified amount val baseUrl = "apps/$appId/subscriptions/$subscriptionId/iams" - return attemptFetchWithRetries(baseUrl, rywToken, sessionDurationProvider) + return attemptFetchWithRetries(baseUrl, rywData, sessionDurationProvider) } override suspend fun getIAMData( @@ -206,7 +207,7 @@ internal class InAppBackendService( private suspend fun attemptFetchWithRetries( baseUrl: String, - rywToken: String?, + rywData: RywData, sessionDurationProvider: () -> Long, ): List? { var attempts = 0 @@ -216,7 +217,7 @@ internal class InAppBackendService( val retryCount = if (attempts > 0) attempts else null val values = OptionalHeaders( - rywToken = rywToken, + rywToken = rywData.rywToken, sessionDuration = sessionDurationProvider(), retryCount = retryCount, ) diff --git a/OneSignalSDK/onesignal/in-app-messages/src/test/java/com/onesignal/inAppMessages/internal/backend/InAppBackendServiceTests.kt b/OneSignalSDK/onesignal/in-app-messages/src/test/java/com/onesignal/inAppMessages/internal/backend/InAppBackendServiceTests.kt index 379013d7c..72f986e0e 100644 --- a/OneSignalSDK/onesignal/in-app-messages/src/test/java/com/onesignal/inAppMessages/internal/backend/InAppBackendServiceTests.kt +++ b/OneSignalSDK/onesignal/in-app-messages/src/test/java/com/onesignal/inAppMessages/internal/backend/InAppBackendServiceTests.kt @@ -1,5 +1,6 @@ package com.onesignal.inAppMessages.internal.backend +import com.onesignal.common.consistency.RywData import com.onesignal.common.exceptions.BackendException import com.onesignal.common.safeBool import com.onesignal.common.safeInt @@ -39,7 +40,7 @@ class InAppBackendServiceTests : val inAppBackendService = InAppBackendService(mockHttpClient, MockHelper.deviceService(), mockHydrator) // When - val response = inAppBackendService.listInAppMessages("appId", "subscriptionId", "123", mockSessionDurationProvider) + val response = inAppBackendService.listInAppMessages("appId", "subscriptionId", RywData("123", 500L), mockSessionDurationProvider) // Then response shouldNotBe null @@ -62,7 +63,7 @@ class InAppBackendServiceTests : val inAppBackendService = InAppBackendService(mockHttpClient, MockHelper.deviceService(), mockHydrator) // When - val response = inAppBackendService.listInAppMessages("appId", "subscriptionId", "123", mockSessionDurationProvider) + val response = inAppBackendService.listInAppMessages("appId", "subscriptionId", RywData("123", 500L), mockSessionDurationProvider) // Then response shouldNotBe null @@ -95,7 +96,7 @@ class InAppBackendServiceTests : val inAppBackendService = InAppBackendService(mockHttpClient, MockHelper.deviceService(), mockHydrator) // When - val response = inAppBackendService.listInAppMessages("appId", "subscriptionId", "123", mockSessionDurationProvider) + val response = inAppBackendService.listInAppMessages("appId", "subscriptionId", RywData("123", 500L), mockSessionDurationProvider) // Then response shouldBe null @@ -124,7 +125,7 @@ class InAppBackendServiceTests : val inAppBackendService = InAppBackendService(mockHttpClient, MockHelper.deviceService(), mockHydrator) // When - val response = inAppBackendService.listInAppMessages("appId", "subscriptionId", "1234", mockSessionDurationProvider) + val response = inAppBackendService.listInAppMessages("appId", "subscriptionId", RywData("1234", 500L), mockSessionDurationProvider) // Then response shouldNotBe null From 2ad40bf7c5bbe33c6022a41ee7ac87a5fe2474bd Mon Sep 17 00:00:00 2001 From: Rodrigo Gomez Palacio Date: Wed, 30 Oct 2024 11:54:25 -0500 Subject: [PATCH 5/9] Rename `getNewestToken` to `getRywData` for clarity Motivation: we switched to return a RywData object so method name didn't make sense any more --- .../onesignal/common/consistency/IamFetchReadyCondition.kt | 2 +- .../onesignal/common/consistency/impl/ConsistencyManager.kt | 2 +- .../com/onesignal/common/consistency/models/ICondition.kt | 2 +- .../onesignal/common/consistency/ConsistencyManagerTests.kt | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/IamFetchReadyCondition.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/IamFetchReadyCondition.kt index 4a07166e1..536db1c1a 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/IamFetchReadyCondition.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/IamFetchReadyCondition.kt @@ -33,7 +33,7 @@ class IamFetchReadyCondition( return userUpdateTokenSet } - override fun getNewestToken(indexedTokens: Map>): RywData? { + override fun getRywData(indexedTokens: Map>): RywData? { val tokenMap = indexedTokens[key] ?: return null // Collect non-null RywData objects and find the one with the largest rywToken lexicographically diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/impl/ConsistencyManager.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/impl/ConsistencyManager.kt index f21e62d77..7169fcbb4 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/impl/ConsistencyManager.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/impl/ConsistencyManager.kt @@ -79,7 +79,7 @@ class ConsistencyManager : IConsistencyManager { for ((condition, deferred) in conditions) { if (condition.isMet(indexedTokens)) { - val rywDataForNewestToken = condition.getNewestToken(indexedTokens) + val rywDataForNewestToken = condition.getRywData(indexedTokens) if (!deferred.isCompleted) { deferred.complete(rywDataForNewestToken) } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/ICondition.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/ICondition.kt index 988d58bb6..0372ae58c 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/ICondition.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/models/ICondition.kt @@ -19,5 +19,5 @@ interface ICondition { * Used to process tokens according to their format & return the newest token. * e.g. numeric strings would be compared differently from JWT tokens */ - fun getNewestToken(indexedTokens: Map>): RywData? + fun getRywData(indexedTokens: Map>): RywData? } diff --git a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/common/consistency/ConsistencyManagerTests.kt b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/common/consistency/ConsistencyManagerTests.kt index 9627eb76a..a374487a1 100644 --- a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/common/consistency/ConsistencyManagerTests.kt +++ b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/common/consistency/ConsistencyManagerTests.kt @@ -89,7 +89,7 @@ class ConsistencyManagerTests : FunSpec({ return false // Always returns false to simulate an unmet condition } - override fun getNewestToken(indexedTokens: Map>): RywData? { + override fun getRywData(indexedTokens: Map>): RywData? { return null } } @@ -109,7 +109,7 @@ class ConsistencyManagerTests : FunSpec({ return indexedTokens == expectedRywTokens } - override fun getNewestToken(indexedTokens: Map>): RywData? { + override fun getRywData(indexedTokens: Map>): RywData? { return expectedRywTokens.values.firstOrNull()?.values?.firstOrNull() } } From 13294168b95b5aade064f5c1f77309475cb78962 Mon Sep 17 00:00:00 2001 From: Rodrigo Gomez Palacio Date: Wed, 30 Oct 2024 14:02:53 -0500 Subject: [PATCH 6/9] Add note on why lexicographic evaluation works for RYW tokens Motivation: add clarity on why the method maxOrNull (which uses lexicographic evaulation for strings) works for this use case. --- .../onesignal/common/consistency/IamFetchReadyCondition.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/IamFetchReadyCondition.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/IamFetchReadyCondition.kt index 536db1c1a..a7906b28a 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/IamFetchReadyCondition.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/IamFetchReadyCondition.kt @@ -36,7 +36,10 @@ class IamFetchReadyCondition( override fun getRywData(indexedTokens: Map>): RywData? { val tokenMap = indexedTokens[key] ?: return null - // Collect non-null RywData objects and find the one with the largest rywToken lexicographically + /** + * Collect non-null RywData objects and find the one with the largest rywToken lexicographically + * Note: this works because RYW tokens are always the same length + */ return listOfNotNull( tokenMap[IamFetchRywTokenKey.USER], tokenMap[IamFetchRywTokenKey.SUBSCRIPTION], From 592cca2850eedb9a2a2f7e8ec04a90f55654fcb3 Mon Sep 17 00:00:00 2001 From: Rodrigo Gomez Palacio Date: Wed, 30 Oct 2024 14:04:12 -0500 Subject: [PATCH 7/9] fixup! Encapsulate `rywToken` & `rywDelay` in `RywData` data class object --- .../src/main/java/com/onesignal/common/consistency/RywData.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/RywData.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/RywData.kt index 4fcf7b3be..4cbd89bd8 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/RywData.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/consistency/RywData.kt @@ -1,3 +1,3 @@ package com.onesignal.common.consistency -data class RywData(val rywToken: String?, val rywDelay: Long?) +data class RywData(val rywToken: String, val rywDelay: Long?) From f6e4a90ab118418dba7af4e9d8ac6cec210b4325 Mon Sep 17 00:00:00 2001 From: Rodrigo Gomez Palacio Date: Wed, 30 Oct 2024 14:08:26 -0500 Subject: [PATCH 8/9] Update RywData usage so `rywToken` is non-null Motivation: rywData shouldn't be considered a valid rywData object if rywToken is undefined. We update usage across the board to account for this type change. --- .../backend/ISubscriptionBackendService.kt | 4 +- .../internal/backend/IUserBackendService.kt | 2 +- .../impl/SubscriptionBackendService.kt | 48 ++++++++++--------- .../backend/impl/UserBackendService.kt | 24 +++++----- .../SubscriptionOperationExecutor.kt | 4 +- .../executors/UpdateUserOperationExecutor.kt | 2 +- .../SubscriptionBackendServiceTests.kt | 4 +- 7 files changed, 46 insertions(+), 42 deletions(-) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/ISubscriptionBackendService.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/ISubscriptionBackendService.kt index 65ade278c..7bcf23fdb 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/ISubscriptionBackendService.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/ISubscriptionBackendService.kt @@ -22,7 +22,7 @@ interface ISubscriptionBackendService { aliasLabel: String, aliasValue: String, subscription: SubscriptionObject, - ): Pair? + ): Pair? /** * Update an existing subscription with the properties provided. @@ -35,7 +35,7 @@ interface ISubscriptionBackendService { appId: String, subscriptionId: String, subscription: SubscriptionObject, - ): RywData + ): RywData? /** * Delete an existing subscription. diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/IUserBackendService.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/IUserBackendService.kt index bc450c16f..4cec114b5 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/IUserBackendService.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/IUserBackendService.kt @@ -48,7 +48,7 @@ interface IUserBackendService { properties: PropertiesObject, refreshDeviceMetadata: Boolean, propertyiesDelta: PropertiesDeltasObject, - ): RywData + ): RywData? /** * Retrieve a user from the backend. diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/SubscriptionBackendService.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/SubscriptionBackendService.kt index 181678058..7940fdd25 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/SubscriptionBackendService.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/SubscriptionBackendService.kt @@ -17,7 +17,7 @@ internal class SubscriptionBackendService( aliasLabel: String, aliasValue: String, subscription: SubscriptionObject, - ): Pair? { + ): Pair? { val jsonSubscription = JSONConverter.convertToJSON(subscription) jsonSubscription.remove("id") val requestJSON = JSONObject().put("subscription", jsonSubscription) @@ -28,23 +28,23 @@ internal class SubscriptionBackendService( throw BackendException(response.statusCode, response.payload, response.retryAfterSeconds) } - val responseJSON = JSONObject(response.payload!!) - val subscriptionJSON = responseJSON.safeJSONObject("subscription") + val responseJSON = response.payload?.let { JSONObject(it) } + val subscriptionJSON = responseJSON?.safeJSONObject("subscription") + if (subscriptionJSON == null || !subscriptionJSON.has("id")) { return null } - var rywToken: String? = null - if (responseJSON.has("ryw_token")) { - rywToken = responseJSON.getString("ryw_token") - } + fun JSONObject.safeString(key: String): String? = if (this.has(key)) this.getString(key) else null - var rywDelay: Long? = null - if (responseJSON.has("ryw_delay")) { - rywDelay = responseJSON.getLong("ryw_delay") - } + fun JSONObject.safeLong(key: String): Long? = if (this.has(key)) this.getLong(key) else null + val rywToken = responseJSON.safeString("ryw_token") + val rywDelay = responseJSON.safeLong("ryw_delay") + var rywData: RywData? = null - var rywData = RywData(rywToken, rywDelay) + if (rywToken != null) { + rywData = RywData(rywToken, rywDelay) + } return Pair(subscriptionJSON.getString("id"), rywData) } @@ -53,7 +53,7 @@ internal class SubscriptionBackendService( appId: String, subscriptionId: String, subscription: SubscriptionObject, - ): RywData { + ): RywData? { val requestJSON = JSONObject() .put("subscription", JSONConverter.convertToJSON(subscription)) @@ -64,18 +64,20 @@ internal class SubscriptionBackendService( throw BackendException(response.statusCode, response.payload, response.retryAfterSeconds) } - val responseJSON = JSONObject(response.payload) - var rywToken: String? = null - if (responseJSON.has("ryw_token")) { - rywToken = responseJSON.getString("ryw_token") - } + fun JSONObject.safeString(key: String): String? = if (this.has(key)) this.getString(key) else null - var rywDelay: Long? = null - if (responseJSON.has("ryw_delay")) { - rywDelay = responseJSON.getLong("ryw_delay") - } + fun JSONObject.safeLong(key: String): Long? = if (this.has(key)) this.getLong(key) else null + + val responseJSON = response.payload?.let { JSONObject(it) } - return RywData(rywToken, rywDelay) + val rywToken = responseJSON?.safeString("ryw_token") + val rywDelay = responseJSON?.safeLong("ryw_delay") + + return if (rywToken !== null) { + RywData(rywToken, rywDelay) + } else { + null + } } override suspend fun deleteSubscription( diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/UserBackendService.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/UserBackendService.kt index 333082541..9da572dbe 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/UserBackendService.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/UserBackendService.kt @@ -53,7 +53,7 @@ internal class UserBackendService( properties: PropertiesObject, refreshDeviceMetadata: Boolean, propertyiesDelta: PropertiesDeltasObject, - ): RywData { + ): RywData? { val jsonObject = JSONObject() .put("refresh_device_metadata", refreshDeviceMetadata) @@ -72,18 +72,20 @@ internal class UserBackendService( throw BackendException(response.statusCode, response.payload, response.retryAfterSeconds) } - val responseJSON = JSONObject(response.payload) - var rywToken: String? = null - if (responseJSON.has("ryw_token")) { - rywToken = responseJSON.getString("ryw_token") - } + fun JSONObject.safeString(key: String): String? = if (this.has(key)) this.getString(key) else null - var rywDelay: Long? = null - if (responseJSON.has("ryw_delay")) { - rywDelay = responseJSON.getLong("ryw_delay") - } + fun JSONObject.safeLong(key: String): Long? = if (this.has(key)) this.getLong(key) else null + + val responseJSON = response.payload?.let { JSONObject(it) } - return RywData(rywToken, rywDelay) + val rywToken = responseJSON?.safeString("ryw_token") + val rywDelay = responseJSON?.safeLong("ryw_delay") + + return if (rywToken != null) { + RywData(rywToken, rywDelay) + } else { + null + } } override suspend fun getUser( diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/SubscriptionOperationExecutor.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/SubscriptionOperationExecutor.kt index 18e44d128..950def5cd 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/SubscriptionOperationExecutor.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/SubscriptionOperationExecutor.kt @@ -116,7 +116,7 @@ internal class SubscriptionOperationExecutor( val backendSubscriptionId = result.first val rywData = result.second - if (rywData.rywToken != null) { + if (rywData?.rywToken != null) { _consistencyManager.setRywData(createOperation.onesignalId, IamFetchRywTokenKey.SUBSCRIPTION, rywData) } else { _consistencyManager.resolveConditionsWithID(IamFetchReadyCondition.ID) @@ -190,7 +190,7 @@ internal class SubscriptionOperationExecutor( val rywData = _subscriptionBackend.updateSubscription(lastOperation.appId, lastOperation.subscriptionId, subscription) - if (rywData.rywToken != null) { + if (rywData?.rywToken != null) { _consistencyManager.setRywData(startingOperation.onesignalId, IamFetchRywTokenKey.SUBSCRIPTION, rywData) } else { _consistencyManager.resolveConditionsWithID(IamFetchReadyCondition.ID) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/UpdateUserOperationExecutor.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/UpdateUserOperationExecutor.kt index 91c6f9460..a97a261f6 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/UpdateUserOperationExecutor.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/UpdateUserOperationExecutor.kt @@ -148,7 +148,7 @@ internal class UpdateUserOperationExecutor( deltasObject, ) - if (rywData.rywToken != null) { + if (rywData?.rywToken != null) { _consistencyManager.setRywData(onesignalId, IamFetchRywTokenKey.USER, rywData) } else { _consistencyManager.resolveConditionsWithID(IamFetchReadyCondition.ID) diff --git a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/backend/SubscriptionBackendServiceTests.kt b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/backend/SubscriptionBackendServiceTests.kt index cabe340dd..4b6ba8896 100644 --- a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/backend/SubscriptionBackendServiceTests.kt +++ b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/user/internal/backend/SubscriptionBackendServiceTests.kt @@ -27,7 +27,7 @@ class SubscriptionBackendServiceTests : FunSpec({ val aliasLabel = "onesignal_id" val aliasValue = "11111111-1111-1111-1111-111111111111" val spyHttpClient = mockk() - coEvery { spyHttpClient.post(any(), any()) } returns HttpResponse(202, "{ \"subscription\": { id: \"subscriptionId\" } }") + coEvery { spyHttpClient.post(any(), any()) } returns HttpResponse(202, "{ \"subscription\": { id: \"subscriptionId\" }, \"ryw_token\": \"123\"}") val subscriptionBackendService = SubscriptionBackendService(spyHttpClient) // When @@ -43,7 +43,7 @@ class SubscriptionBackendServiceTests : FunSpec({ val response = subscriptionBackendService.createSubscription("appId", aliasLabel, aliasValue, subscription) // Then - response shouldBe Pair("subscriptionId", RywData(null, null)) + response shouldBe Pair("subscriptionId", RywData("123", null)) coVerify { spyHttpClient.post( "apps/appId/users/by/$aliasLabel/$aliasValue/subscriptions", From ec5e3dd4127c0d5343d935dff6cfb97fe3418323 Mon Sep 17 00:00:00 2001 From: Rodrigo Gomez Palacio Date: Wed, 30 Oct 2024 18:01:25 -0500 Subject: [PATCH 9/9] fixup! Update RywData usage so `rywToken` is non-null --- .../backend/impl/SubscriptionBackendService.kt | 10 ++-------- .../user/internal/backend/impl/UserBackendService.kt | 6 ++---- .../impl/executors/SubscriptionOperationExecutor.kt | 4 ++-- .../impl/executors/UpdateUserOperationExecutor.kt | 2 +- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/SubscriptionBackendService.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/SubscriptionBackendService.kt index 7940fdd25..3b5a2f408 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/SubscriptionBackendService.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/SubscriptionBackendService.kt @@ -3,6 +3,8 @@ package com.onesignal.user.internal.backend.impl import com.onesignal.common.consistency.RywData import com.onesignal.common.exceptions.BackendException import com.onesignal.common.safeJSONObject +import com.onesignal.common.safeLong +import com.onesignal.common.safeString import com.onesignal.common.toMap import com.onesignal.core.internal.http.IHttpClient import com.onesignal.user.internal.backend.ISubscriptionBackendService @@ -34,10 +36,6 @@ internal class SubscriptionBackendService( if (subscriptionJSON == null || !subscriptionJSON.has("id")) { return null } - - fun JSONObject.safeString(key: String): String? = if (this.has(key)) this.getString(key) else null - - fun JSONObject.safeLong(key: String): Long? = if (this.has(key)) this.getLong(key) else null val rywToken = responseJSON.safeString("ryw_token") val rywDelay = responseJSON.safeLong("ryw_delay") var rywData: RywData? = null @@ -64,10 +62,6 @@ internal class SubscriptionBackendService( throw BackendException(response.statusCode, response.payload, response.retryAfterSeconds) } - fun JSONObject.safeString(key: String): String? = if (this.has(key)) this.getString(key) else null - - fun JSONObject.safeLong(key: String): Long? = if (this.has(key)) this.getLong(key) else null - val responseJSON = response.payload?.let { JSONObject(it) } val rywToken = responseJSON?.safeString("ryw_token") diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/UserBackendService.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/UserBackendService.kt index 9da572dbe..1a1514018 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/UserBackendService.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/backend/impl/UserBackendService.kt @@ -3,6 +3,8 @@ package com.onesignal.user.internal.backend.impl import com.onesignal.common.consistency.RywData import com.onesignal.common.exceptions.BackendException import com.onesignal.common.putMap +import com.onesignal.common.safeLong +import com.onesignal.common.safeString import com.onesignal.core.internal.http.IHttpClient import com.onesignal.user.internal.backend.CreateUserResponse import com.onesignal.user.internal.backend.IUserBackendService @@ -72,10 +74,6 @@ internal class UserBackendService( throw BackendException(response.statusCode, response.payload, response.retryAfterSeconds) } - fun JSONObject.safeString(key: String): String? = if (this.has(key)) this.getString(key) else null - - fun JSONObject.safeLong(key: String): Long? = if (this.has(key)) this.getLong(key) else null - val responseJSON = response.payload?.let { JSONObject(it) } val rywToken = responseJSON?.safeString("ryw_token") diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/SubscriptionOperationExecutor.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/SubscriptionOperationExecutor.kt index 950def5cd..334e47b89 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/SubscriptionOperationExecutor.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/SubscriptionOperationExecutor.kt @@ -116,7 +116,7 @@ internal class SubscriptionOperationExecutor( val backendSubscriptionId = result.first val rywData = result.second - if (rywData?.rywToken != null) { + if (rywData != null) { _consistencyManager.setRywData(createOperation.onesignalId, IamFetchRywTokenKey.SUBSCRIPTION, rywData) } else { _consistencyManager.resolveConditionsWithID(IamFetchReadyCondition.ID) @@ -190,7 +190,7 @@ internal class SubscriptionOperationExecutor( val rywData = _subscriptionBackend.updateSubscription(lastOperation.appId, lastOperation.subscriptionId, subscription) - if (rywData?.rywToken != null) { + if (rywData != null) { _consistencyManager.setRywData(startingOperation.onesignalId, IamFetchRywTokenKey.SUBSCRIPTION, rywData) } else { _consistencyManager.resolveConditionsWithID(IamFetchReadyCondition.ID) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/UpdateUserOperationExecutor.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/UpdateUserOperationExecutor.kt index a97a261f6..e529035ec 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/UpdateUserOperationExecutor.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/UpdateUserOperationExecutor.kt @@ -148,7 +148,7 @@ internal class UpdateUserOperationExecutor( deltasObject, ) - if (rywData?.rywToken != null) { + if (rywData != null) { _consistencyManager.setRywData(onesignalId, IamFetchRywTokenKey.USER, rywData) } else { _consistencyManager.resolveConditionsWithID(IamFetchReadyCondition.ID)