TP-66010 | Litmus Experimentation setup for upi (#10759)

This commit is contained in:
Shaurya Rehan
2024-05-08 19:25:27 +05:30
committed by GitHub
parent 9bcb28bd7d
commit 8ceeb88387
8 changed files with 156 additions and 0 deletions

View File

@@ -111,6 +111,8 @@ object FirebaseRemoteConfigHelper {
const val NAVI_PAY_REWARDS_NUDGE_ENABLED = "NAVI_PAY_REWARDS_NUDGE_ENABLED"
const val NAVI_PAY_REWARDS_GRATIFICATION_ENABLED = "NAVI_PAY_REWARDS_GRATIFICATION_ENABLED"
const val NAVI_PAY_CL_INIT_RETRY_COUNT = "NAVI_PAY_CL_INIT_RETRY_COUNT"
const val NAVI_PAY_LITMUS_EXPERIMENTS_CACHE_DURATION_IN_MILLIS =
"NAVI_PAY_LITMUS_EXPERIMENTS_CACHE_DURATION_IN_MILLIS"
// BBPS
const val NAVI_BBPS_CATEGORIES_CACHE_MILLIS = "NAVI_BBPS_CATEGORIES_CACHE_MILLIS"

View File

@@ -477,4 +477,8 @@
<key>FRONT_LAYER_UPPER_CONTENT_LENGTH</key>
<value>7</value>
</entry>
<entry>
<key>NAVI_PAY_LITMUS_EXPERIMENTS_CACHE_DURATION_IN_MILLIS</key>
<value>86400000</value>
</entry>
</defaultsMap>

View File

@@ -0,0 +1,20 @@
/*
*
* * Copyright © 2024 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.pay.common.model.network
import com.google.gson.annotations.SerializedName
data class LitmusExperimentsResponse(
@SerializedName("experiments") val experiments: List<LitmusExperimentItemResponse>?
)
data class LitmusExperimentItemResponse(
@SerializedName("name") val name: String,
@SerializedName("isEnabled") val isEnabled: Boolean? = false,
@SerializedName("metaData") val metaData: Map<String, String>? = emptyMap()
)

View File

@@ -88,4 +88,7 @@ constructor(private val naviPayRetrofitService: NaviPayRetrofitService) : Respon
suspend fun liteDeregistration(sendMoneyRequest: SendMoneyRequest) =
apiResponseCallback(naviPayRetrofitService.sendMoney(sendMoneyRequest = sendMoneyRequest))
suspend fun fetchABTestingExperiments() =
apiResponseCallback(response = naviPayRetrofitService.fetchABTestingExperiments())
}

View File

@@ -0,0 +1,114 @@
/*
*
* * Copyright © 2024 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.pay.common.usecase
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.navi.base.cache.model.NaviCacheAltSourceEntity
import com.navi.base.cache.model.NaviCacheEntity
import com.navi.base.cache.repository.NaviCacheRepository
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
import com.navi.common.network.models.isSuccessWithData
import com.navi.pay.common.model.network.LitmusExperimentItemResponse
import com.navi.pay.common.repository.CommonRepository
import com.navi.pay.common.sync.model.view.SyncEntity
import com.navi.pay.common.sync.repository.SyncRepository
import com.navi.pay.network.di.NaviPayGsonBuilder
import com.navi.pay.utils.NAVI_PAY_LITMUS_EXPERIMENTS_CACHE_KEY
import com.navi.pay.utils.NAVI_PAY_LITMUS_EXPERIMENTS_LAST_REFRESHED_TIMESTAMP
import javax.inject.Inject
class SyncLitmusExperimentsUseCase
@Inject
constructor(
private val commonRepository: CommonRepository,
private val naviCacheRepository: NaviCacheRepository,
private val syncRepository: SyncRepository,
@NaviPayGsonBuilder private val gson: Gson
) {
suspend fun execute(skipLastSyncedTimestampCheck: Boolean = true) {
val firebaseCacheDurationInMillis =
FirebaseRemoteConfigHelper.getLong(
FirebaseRemoteConfigHelper.NAVI_PAY_LITMUS_EXPERIMENTS_CACHE_DURATION_IN_MILLIS
)
val lastRefreshTimeStampForABTesting =
syncRepository
.get(key = NAVI_PAY_LITMUS_EXPERIMENTS_LAST_REFRESHED_TIMESTAMP)
?.lastSyncedTimestamp
?.toLongOrNull() ?: 0L
if (!skipLastSyncedTimestampCheck) {
// Refresh is not needed
if (
System.currentTimeMillis() - lastRefreshTimeStampForABTesting <
firebaseCacheDurationInMillis
) {
return
}
}
val abTestingResponse = commonRepository.fetchABTestingExperiments()
if (!abTestingResponse.isSuccessWithData()) {
return
}
naviCacheRepository.save(
NaviCacheEntity(
value = gson.toJson(abTestingResponse.data?.experiments),
ttl = firebaseCacheDurationInMillis,
version = 1,
key = NAVI_PAY_LITMUS_EXPERIMENTS_CACHE_KEY
)
)
syncRepository.insert(
syncEntity =
SyncEntity(
key = NAVI_PAY_LITMUS_EXPERIMENTS_LAST_REFRESHED_TIMESTAMP,
lastSyncedTimestamp = System.currentTimeMillis().toString()
)
)
}
private suspend fun getABExperiments(): List<LitmusExperimentItemResponse> {
val experimentsJson =
naviCacheRepository.getDataOrFetchFromAltSource(
key = NAVI_PAY_LITMUS_EXPERIMENTS_CACHE_KEY,
version = 1,
getDataFromAltSource = {
NaviCacheAltSourceEntity(
value = gson.toJson(emptyList<LitmusExperimentItemResponse>()),
version = 1,
isSuccess = false
)
}
)
val type = object : TypeToken<List<LitmusExperimentItemResponse>>() {}.type
val experiments =
try {
gson
.fromJson<List<LitmusExperimentItemResponse>>(
experimentsJson?.value.orEmpty(),
type
)
.let { it.ifEmpty { emptyList() } }
} catch (e: Exception) {
emptyList()
}
return experiments
}
private suspend fun getExperimentValues(experimentName: String): LitmusExperimentItemResponse? {
return getABExperiments().firstOrNull { it.name == experimentName }
}
}

View File

@@ -33,6 +33,7 @@ import com.navi.pay.common.usecase.RefreshBankListUseCase
import com.navi.pay.common.usecase.RefreshConfigUseCase
import com.navi.pay.common.usecase.RefreshLinkedAccountsUseCase
import com.navi.pay.common.usecase.RefreshUiTronScreenResponseUseCase
import com.navi.pay.common.usecase.SyncLitmusExperimentsUseCase
import com.navi.pay.common.viewmodel.NaviPayBaseVM
import com.navi.pay.management.common.model.view.NudgeDetailEntity
import com.navi.pay.network.di.NaviPayGsonBuilder
@@ -76,6 +77,7 @@ constructor(
private val bankUptimeRepository: BankUptimeRepository,
private val scratchCardNudgeHelper: ScratchCardNudgeHelper,
private val naviCacheRepository: NaviCacheRepository,
private val syncLitmusExperimentsUseCase: SyncLitmusExperimentsUseCase,
@NaviPayGsonBuilder private val gson: Gson
) : NaviPayBaseVM(naviPayVmData = NaviPayVmData(screenName = NaviPayAnalytics.NAVI_PAY_ACTIVITY)) {
@@ -106,6 +108,10 @@ constructor(
taskList.add(async { refreshConfigUseCase.execute() })
taskList.add(
async { syncLitmusExperimentsUseCase.execute(skipLastSyncedTimestampCheck = false) }
)
taskList.add(
async {
if (isUserOnboarded()) {

View File

@@ -8,6 +8,7 @@
package com.navi.pay.network.retrofit
import com.navi.common.network.models.GenericResponse
import com.navi.pay.common.model.network.LitmusExperimentsResponse
import com.navi.pay.common.model.network.RequestIdResponse
import com.navi.pay.common.model.network.ValidateVpaRequest
import com.navi.pay.common.model.network.ValidateVpaResponse
@@ -396,4 +397,7 @@ interface NaviPayRetrofitService {
suspend fun sendMoneyAdditionalInfo(
@Body sendMoneyAdditionalInfoRequest: SendMoneyAdditionalInfoRequest
): Response<GenericResponse<Any?>>
@GET("/gateway-service/$NAVI_PAY_API_VERSION/navipay/user-experiments")
suspend fun fetchABTestingExperiments(): Response<GenericResponse<LitmusExperimentsResponse>>
}

View File

@@ -153,6 +153,7 @@ const val DEFAULT_INITIATION_MODE_DYNAMIC_ATM_QR = "18"
// Navi Pay cache keys
const val NPCI_KEY = "npciKey"
const val NAVI_PAY_LITMUS_EXPERIMENTS_CACHE_KEY = "NAVI_PAY_LITMUS_EXPERIMENTS_CACHE_KEY"
// Navi Common DB cache keys
const val NAVI_PAY_HOME_PAGE_CACHE_KEY = "naviPayHomePage"
@@ -163,6 +164,8 @@ const val NAVI_PAY_SYNC_TABLE_TRANSACTION_HISTORY_KEY = "transactionHistoryKey"
const val NAVI_PAY_SYNC_TABLE_LINKED_ACCOUNTS_KEY = "linkedAccountsKey"
const val NAVI_PAY_SYNC_TABLE_SAVED_BENEFICIARY_KEY = "savedBeneficiaryKey"
const val NAVI_PAY_SYNC_TABLE_FREQUENT_TRANSACTIONS_KEY = "frequentTransactionsKey"
const val NAVI_PAY_LITMUS_EXPERIMENTS_LAST_REFRESHED_TIMESTAMP =
"litmusExperimentsLastRefreshedTimestamp"
// Generic
const val NAVIPAY_NETWORK_INFO_TIMEOUT = 65L