TP-66121 | [GI] - Implementing an Efficient Cache Mechanism for Seamless User Experience (#11108)

This commit is contained in:
Balrambhai Sharma
2024-09-24 17:55:32 +05:30
committed by GitHub
parent b20faa4526
commit 9b0d5b80f5
13 changed files with 124 additions and 28 deletions

View File

@@ -86,6 +86,7 @@ class InsuranceTabFragment(private val lazyListState: () -> LazyListState? = { n
setContent { RenderUiTronDataSecondary(lazyListState) }
}
observeCtaData()
viewModel.clearCacheOnVersionUpgrade()
if (
FirebaseRemoteConfigHelper.getBoolean(
key = FirebaseRemoteConfigHelper.ENABLE_REACT_PREFETCH_IN_TAB,

View File

@@ -13,6 +13,7 @@ import com.navi.common.network.models.RepoResult
import com.navi.common.network.retrofit.ResponseCallback
import com.navi.common.utils.Constants.GZIP
import com.navi.common.utils.TemporaryStorageHelper
import com.navi.insurance.common.models.ClearCacheResponse
import com.navi.insurance.common.models.InsuranceTabResponse
import com.navi.insurance.common.models.ToastRequestBody
import com.navi.insurance.models.response.ClosePolicyCardResponse
@@ -50,4 +51,12 @@ constructor(@SuperAppRetroFit private val apiService: RetrofitService) : Respons
apiService.closePolicyCard(applicationId = quoteId, target = ModuleName.GI.name)
)
}
suspend fun clearCache(): RepoResult<ClearCacheResponse> {
return apiResponseCallback(
apiService.clearCache(
target = ModuleName.GI.name,
)
)
}
}

View File

@@ -10,6 +10,7 @@ package com.naviapp.common.tab
import androidx.lifecycle.viewModelScope
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.navi.analytics.utils.NaviTrackEvent
import com.navi.base.cache.repository.NaviCacheRepository
import com.navi.base.model.CtaData
import com.navi.base.utils.isNotNull
import com.navi.base.utils.isNull
@@ -20,6 +21,7 @@ import com.navi.common.model.ModuleNameV2
import com.navi.common.network.models.ErrorMetaData
import com.navi.common.uitron.model.action.CtaAction
import com.navi.common.utils.SingleLiveEvent
import com.navi.common.utils.isValidResponse
import com.navi.common.viewmodel.BaseVM
import com.navi.insurance.common.models.GiErrorMetaData
import com.navi.insurance.common.models.InsuranceTabState
@@ -41,6 +43,7 @@ class InsuranceTabViewModel
@Inject
constructor(
private val repository: InsuranceTabRepository,
private val naviCacheRepository: NaviCacheRepository
) : BaseVM() {
init {
@@ -191,4 +194,36 @@ constructor(
private fun handleCtaAction(ctaAction: CtaAction) {
ctaAction.ctaData?.let { ctaData -> redirectionCta.postValue(ctaAction.ctaData) }
}
fun clearCacheOnVersionUpgrade() {
viewModelScope.safeLaunch(coroutineContext = Dispatchers.IO) {
val response = repository.clearCache()
if (response.isValidResponse()) {
response.data?.pageVersionList?.forEach { item ->
val entity = naviCacheRepository.get(key = item.pageName.orEmpty())
entity?.let {
if (it.version != item.version.orZero()) {
naviCacheRepository.clear(key = item.pageName.orEmpty())
}
}
}
} else {
val errorUnifiedResponse =
getErrorUnifiedResponse(
errors = response.errors,
error = response.error,
errorMetaData =
ErrorMetaData(
methodName = ApiErrorTagType.INSURANCE_TAB_SCREEN_PAGE_ERROR.value,
flowName = GiErrorMetaData.INSURANCE_TAB_FLOW
)
)
sendFailureEvent(
NaviAnalytics.INSURANCE_TAB_INIT,
errorUnifiedResponse,
ModuleNameV2.Insurance.name
)
}
}
}
}

View File

@@ -57,6 +57,7 @@ import com.navi.common.utils.Constants.HEADER_VERTICAL_TYPE
import com.navi.common.utils.Constants.HEADER_X_PLATFORM
import com.navi.common.utils.Constants.HEADER_X_TENANT_ID
import com.navi.common.utils.Constants.ScreenLockConstants.X_IS_MOBILE_SCREEN_LOCK_SET
import com.navi.insurance.common.models.ClearCacheResponse
import com.navi.insurance.common.models.InsuranceTabResponse
import com.navi.insurance.common.models.ToastRequestBody
import com.navi.insurance.models.request.FlagUpdateRequest
@@ -1836,6 +1837,11 @@ interface RetrofitService {
@Header("X-Target") target: String = ModuleName.SAPHYRA.name,
): Response<GenericResponse<Any>>
@GET("/gi/static-pages/versions")
suspend fun clearCache(
@Header("X-Target") target: String
): Response<GenericResponse<ClearCacheResponse>>
@GET("/forge/screen/{screenId}")
suspend fun fetchInvestmentTabForgeScreen(
@Header(X_IS_MOBILE_SCREEN_LOCK_SET) isMobileScreenLockSet: Boolean? = null,

View File

@@ -12,7 +12,9 @@ object DBCacheConstants {
const val NAVI_HL_INTRO_SCREEN_CACHE_KEY = "NAVI_HL_INTRO_SCREEN_CACHE_KEY"
const val NAVI_GI_LANDING_PAGE_CACHE_KEY = "NAVI_GI_LANDING_PAGE_CACHE_KEY"
const val NAVI_GI_BENEFIT_PAGE_CACHE_KEY = "NAVI_GI_BENEFIT_PAGE_CACHE_KEY"
const val GI_PRE_DIAB_RESULT_CACHE_KEY = "GI_PRE_DIAB_RESULT_CACHE_KEY"
const val DIGITAL_CLAIMS_PRE_PURCHASE_DATA = "DIGITAL_CLAIMS_PRE_PURCHASE_DATA"
const val NAVI_GI_AUTOPAY_SUMMARY_SCREEN_CACHE_KEY = "NAVI_GI_AUTOPAY_SUMMARY_SCREEN_CACHE_KEY"
const val PD_QUESTIONNAIRE_PAGE = "PD_QUESTIONNAIRE_PAGE"
const val GI_PRE_DIAB_QUESTION_CACHE_KEY = "GI_PRE_DIAB_QUESTION_CACHE_KEY"
const val COIN_HOME_SCREEN_CACHE_KEY = "COIN_HOME_SCREEN_CACHE_KEY"
const val LEADERBOARD_SCREEN_CACHE_KEY = "LEADERBOARD_SCREEN_CACHE_KEY"

View File

@@ -0,0 +1,19 @@
/*
*
* * Copyright © 2024 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.insurance.common.models
import com.google.gson.annotations.SerializedName
data class ClearCacheResponse(
@SerializedName("pageVersions") val pageVersionList: List<PageVersion>? = null,
)
data class PageVersion(
@SerializedName("pageName") val pageName: String? = null,
@SerializedName("version") val version: Int? = null,
)

View File

@@ -14,6 +14,7 @@ import com.google.gson.Gson
import com.navi.base.cache.model.NaviCacheAltSourceEntity
import com.navi.base.cache.repository.NaviCacheRepository
import com.navi.base.model.CtaData
import com.navi.common.constants.DBCacheConstants
import com.navi.common.constants.VENDOR_NAVI_API
import com.navi.common.di.CoroutineDispatcherProvider
import com.navi.common.model.ModuleName
@@ -114,8 +115,14 @@ constructor(
if (type.equals(SUMMARY_INSURANCE_TAB)) {
val cachedResponse =
naviCacheRepository.getDataOrFetchFromAltSource(
SUMMARY_INSURANCE_TAB,
getDataFromAltSource = { getPageResponseFromAPI(type, policyId) }
key = DBCacheConstants.NAVI_GI_AUTOPAY_SUMMARY_SCREEN_CACHE_KEY,
getDataFromAltSource = {
getPageResponseFromAPI(
type,
policyId,
key = DBCacheConstants.NAVI_GI_AUTOPAY_SUMMARY_SCREEN_CACHE_KEY
)
}
)
RepoResult(
statusCode = 200,
@@ -151,8 +158,10 @@ constructor(
private suspend fun getPageResponseFromAPI(
pageType: String?,
policyId: String?
policyId: String?,
key: String
): NaviCacheAltSourceEntity {
val version = 1
val response =
incentiviseAutopayRepository.fetchIncentiviseAutopayResponse(pageType, policyId)
@@ -173,7 +182,7 @@ constructor(
return NaviCacheAltSourceEntity(
value = Gson().toJson(response.data!!),
isSuccess = true,
version = 1
version = version
)
}

View File

@@ -63,7 +63,7 @@ constructor(
val landingPageResponse =
if (requestPageType == LandingPageInfoFragment.STATIC_BENEFITS_SCREEN) {
naviCacheRepository.getDataOrFetchFromAltSource(
key = DBCacheConstants.NAVI_GI_BENEFIT_PAGE_CACHE_KEY + tabId.orEmpty(),
key = DBCacheConstants.NAVI_GI_BENEFIT_PAGE_CACHE_KEY,
version = cacheVersion.toLong(),
getDataFromAltSource = {
fetchStaticBenefitsResponseFromApi(
@@ -71,7 +71,8 @@ constructor(
applicationType,
tabId,
preQuoteExists,
cacheVersion
cacheVersion,
DBCacheConstants.NAVI_GI_BENEFIT_PAGE_CACHE_KEY
)
}
)
@@ -150,11 +151,13 @@ constructor(
applicationType: String? = null,
tabId: String? = null,
preQuoteExists: Boolean? = null,
cacheVersion: Int
cacheVersion: Int,
key: String
): NaviCacheAltSourceEntity {
val version = cacheVersion
if (requestPageType.isNullOrEmpty()) {
_landingInfoPageResponseStateFlow.emit(LandingPageInfoState.Error)
return NaviCacheAltSourceEntity(value = null, version = cacheVersion, isSuccess = true)
return NaviCacheAltSourceEntity(value = null, version = version, isSuccess = true)
}
val response =
landingPageInfoRepository.fetchBenefitPageInfo(
@@ -166,7 +169,7 @@ constructor(
if (response.error == null && response.errors.isNullOrEmpty() && response.data != null) {
return NaviCacheAltSourceEntity(
value = Gson().toJson(response.data),
version = response.data?.screenVersion ?: 1,
version = version,
isSuccess = true
)
// TODO remove
@@ -182,7 +185,7 @@ constructor(
)
)
}
return NaviCacheAltSourceEntity(value = null, version = cacheVersion, isSuccess = true)
return NaviCacheAltSourceEntity(value = null, version = version, isSuccess = true)
}
private fun saveFooterCta(landingPageInfoResponse: LandingPageInfoResponse?) {

View File

@@ -15,5 +15,6 @@ data class PdResultsData(
@SerializedName("screenVersion") val screenVersion: Int? = null,
@SerializedName("widgetData") val widgetData: List<GenericWidgetDataInfo>? = null,
@SerializedName("footerWidget") val footerWidget: GenericWidgetDataInfo? = null,
@SerializedName("resultBackButtonCta") val resultBackButtonCta: CtaData? = null
@SerializedName("resultBackButtonCta") val resultBackButtonCta: CtaData? = null,
@SerializedName("pageVersion") val pageVersion: Int? = null,
)

View File

@@ -120,7 +120,12 @@ constructor(
naviCacheRepository.getDataOrFetchFromAltSource(
key = DBCacheConstants.GI_PRE_DIAB_QUESTION_CACHE_KEY,
version = cacheVersion.toLong(),
getDataFromAltSource = { getQuestionnaireDataFromApi(cacheVersion) }
getDataFromAltSource = {
getQuestionnaireDataFromApi(
cacheVersion,
key = DBCacheConstants.GI_PRE_DIAB_QUESTION_CACHE_KEY
)
}
)
response?.let { naviCacheEntity ->
@@ -136,7 +141,11 @@ constructor(
}
}
private suspend fun getQuestionnaireDataFromApi(cacheVersion: Int): NaviCacheAltSourceEntity {
private suspend fun getQuestionnaireDataFromApi(
cacheVersion: Int,
key: String
): NaviCacheAltSourceEntity {
val version = cacheVersion
val response = repository.getQuestionnaireData()
if (response.error == null && response.errors.isNullOrEmpty() && response.data != null) {
@@ -158,7 +167,7 @@ constructor(
)
)
}
return NaviCacheAltSourceEntity(value = null, version = cacheVersion, isSuccess = true)
return NaviCacheAltSourceEntity(value = null, version = version, isSuccess = true)
}
fun getResultScreenData(cacheVersion: Int = 0, overrideScoreType: String? = null) {
@@ -187,12 +196,10 @@ constructor(
_scoreRangeFlow.emit(overrideScoreType ?: scoreType)
val response =
naviCacheRepository.getDataOrFetchFromAltSource(
key =
DBCacheConstants.GI_PRE_DIAB_RESULT_CACHE_KEY +
(overrideScoreType ?: scoreType),
key = DBCacheConstants.PD_QUESTIONNAIRE_PAGE + (overrideScoreType ?: scoreType),
version = cacheVersion.toLong(),
getDataFromAltSource = {
getResultScreenDataFromApi((overrideScoreType ?: scoreType), cacheVersion)
getResultScreenDataFromApi((overrideScoreType ?: scoreType))
}
)
@@ -210,14 +217,13 @@ constructor(
private suspend fun getResultScreenDataFromApi(
scoreType: String,
cacheVersion: Int
): NaviCacheAltSourceEntity {
val response = repository.getResultScreenData(scoreType)
if (response.error == null && response.errors.isNullOrEmpty() && response.data != null) {
return NaviCacheAltSourceEntity(
value = Gson().toJson(response.data),
version = 1,
version = response.data?.pageVersion ?: 1,
isSuccess = true
)
} else {
@@ -233,7 +239,11 @@ constructor(
)
)
}
return NaviCacheAltSourceEntity(value = null, version = cacheVersion, isSuccess = true)
return NaviCacheAltSourceEntity(
value = null,
version = response.data?.pageVersion ?: 1,
isSuccess = true
)
}
private fun saveScoreToBackend(score: Float?) {

View File

@@ -24,6 +24,7 @@ data class DigitalClaimScreenResponse(
@SerializedName("bulletIcon") val bulletIcon: ImageFieldData? = null,
@SerializedName("firstTabContent") val firstTabContent: TabContent? = null,
@SerializedName("secondTabContent") val secondTabContent: TabContent? = null,
@SerializedName("pageVersion") val pageVersion: Int? = null,
)
@Parcelize

View File

@@ -12,6 +12,7 @@ import com.google.gson.Gson
import com.navi.base.cache.model.NaviCacheAltSourceEntity
import com.navi.base.cache.repository.NaviCacheRepository
import com.navi.common.ResponseState
import com.navi.common.constants.DBCacheConstants
import com.navi.common.di.CoroutineDispatcherProvider
import com.navi.common.model.ModuleName
import com.navi.common.network.models.RepoResult
@@ -20,7 +21,6 @@ import com.navi.common.utils.CommonNaviAnalytics
import com.navi.insurance.common.GiBaseVM
import com.navi.insurance.common.models.GiErrorMetaData
import com.navi.insurance.common.util.ActionHandler
import com.navi.insurance.common.util.NavigationHandler
import com.navi.insurance.network.ApiErrorTagType
import com.navi.insurance.static_digital_claim.model.DigitalClaimScreenResponse
import com.navi.insurance.static_digital_claim.repository.DigitalClaimRepository
@@ -83,7 +83,7 @@ constructor(
_responseDataFlow.emit(ResponseState.Loading)
val cachedResponse =
naviCacheRepository.getDataOrFetchFromAltSource(
NavigationHandler.URL_STATIC_DIGITAL_CLAIM,
DBCacheConstants.DIGITAL_CLAIMS_PRE_PURCHASE_DATA,
getDataFromAltSource = { getPageResponseFromAPI() }
)
val response =
@@ -135,7 +135,7 @@ constructor(
return NaviCacheAltSourceEntity(
value = Gson().toJson(response.data!!),
isSuccess = true,
version = 1
version = response.data?.pageVersion ?: 1
)
}

View File

@@ -25,7 +25,7 @@ export const get = async <T>(
baseURL: baseUrl ? baseUrl : BASE_URL,
timeout: 10000,
headers: requestConfig.headers,
signal: newAbortSignal(11000)
signal: newAbortSignal(11000),
});
addBundleVersionToHeader(axiosInstance);
@@ -52,7 +52,7 @@ export const post = async <T>(
baseURL: baseUrl ? baseUrl : BASE_URL,
timeout: 10000,
headers: requestConfig.headers,
signal: newAbortSignal(11000)
signal: newAbortSignal(11000),
});
addBundleVersionToHeader(axiosInstance);
@@ -83,7 +83,7 @@ export const patch = async <T>(
baseURL: baseUrl ? baseUrl : BASE_URL,
timeout: 10000,
headers: requestConfig.headers,
signal: newAbortSignal(11000)
signal: newAbortSignal(11000),
});
addBundleVersionToHeader(axiosInstance);