NTP-75213 | bbps transsion db crash fix experiment (#16755)

This commit is contained in:
Mohit Rajput
2025-06-27 02:59:21 -07:00
committed by GitHub
parent 9e4e8316f7
commit 6a6116f8f6
4 changed files with 219 additions and 6 deletions

View File

@@ -56,6 +56,13 @@ class NaviBbpsAnalytics private constructor() {
eventValues = mapOf("errorConfig" to errorConfig.toString()),
)
}
fun onTranssionDeviceData(eventValues: Map<String, String>) {
NaviTrackEvent.trackEventOnClickStream(
eventName = "Dev_NaviBBPS_TranssionCrashFixExperiment",
eventValues = eventValues,
)
}
}
inner class BillCategories {

View File

@@ -0,0 +1,202 @@
/*
*
* * Copyright © 2024-2025 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.bbps.db
import android.os.Build
import androidx.room.RoomDatabase
import androidx.sqlite.db.SupportSQLiteDatabase
import com.navi.analytics.firebase.FcmAnalyticsUtil
import com.navi.bbps.common.NaviBbpsAnalytics
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper.NAVI_BBPS_TRANSSION_DB_CRASH_FIX_ENABLED
import java.util.concurrent.Executors
/**
* A/B Test configuration for Transsion phone database compatibility fixes
*
* This experiment tests enhanced SQLite settings specifically for Transsion devices to resolve
* SQLiteCantOpenDatabaseException crashes.
*
* Test Groups:
* - CONTROL: Current default Room database settings
* - EXPERIMENT: Enhanced compatibility with PRAGMA settings and TRUNCATE journal mode
*/
class TranssionDbExperiment {
private val analytics = NaviBbpsAnalytics.INSTANCE.GenericDev()
/**
* Applies database configuration based on A/B test group
*
* @param builder Room database builder to configure
*/
fun applyDbFixes(builder: RoomDatabase.Builder<*>) {
if (!isTranssionDevice()) {
// Non-Transsion devices: no changes
return
}
val isExperimentEnabled =
FirebaseRemoteConfigHelper.getBoolean(NAVI_BBPS_TRANSSION_DB_CRASH_FIX_ENABLED)
FcmAnalyticsUtil.analytics.trackEvent(
eventName = "TranssionDbExperiment init",
eventValues =
mapOf("isTranssionDbFixExperimentEnabled" to isExperimentEnabled.toString()),
)
if (isExperimentEnabled) {
applyExperimentalFixes(builder)
} else {
applyControlGroupLogging(builder)
}
}
private fun applyExperimentalFixes(builder: RoomDatabase.Builder<*>) {
logExperimentMetrics(
group = "EXPERIMENT",
event = "configuration_started",
success = true,
errorMessage = "Applying Transsion DB fixes",
)
builder.apply {
setJournalMode(RoomDatabase.JournalMode.TRUNCATE)
addCallback(
object : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
logExperimentMetrics(
group = "EXPERIMENT",
event = "database_created",
success = true,
errorMessage = "Database onCreate for ${Build.MODEL}",
)
try {
db.execSQL("PRAGMA journal_mode=DELETE")
db.execSQL("PRAGMA synchronous=NORMAL")
logExperimentMetrics(
group = "EXPERIMENT",
event = "pragma_applied",
success = true,
errorMessage = "PRAGMA settings applied successfully",
)
} catch (e: Exception) {
logExperimentMetrics(
group = "EXPERIMENT",
event = "pragma_failed",
success = false,
errorMessage = e.message,
)
}
}
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
logExperimentMetrics(
group = "EXPERIMENT",
event = "database_opened",
success = true,
errorMessage = "Database onOpen for ${Build.MODEL}",
)
try {
db.execSQL("PRAGMA integrity_check")
logExperimentMetrics(
group = "EXPERIMENT",
event = "integrity_check_passed",
success = true,
errorMessage = "Database integrity check passed",
)
} catch (e: Exception) {
logExperimentMetrics(
group = "EXPERIMENT",
event = "integrity_check_failed",
success = false,
errorMessage = e.message,
)
}
}
}
)
}
}
private fun applyControlGroupLogging(builder: RoomDatabase.Builder<*>) {
logExperimentMetrics(
group = "CONTROL",
event = "configuration_started",
success = true,
errorMessage = "Using default DB settings",
)
builder.apply {
setQueryCallback(
{ sqlQuery, bindArgs ->
logExperimentMetrics(
group = "CONTROL",
event = "query_executed",
success = true,
errorMessage = "Query: $sqlQuery, args: ${bindArgs.joinToString()}",
)
},
Executors.newSingleThreadExecutor(),
)
addCallback(
object : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
logExperimentMetrics(
group = "CONTROL",
event = "database_created",
success = true,
errorMessage = "Database onCreate for ${Build.MODEL}",
)
}
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
logExperimentMetrics(
group = "CONTROL",
event = "database_opened",
success = true,
errorMessage = "Database onOpen for ${Build.MODEL}",
)
}
}
)
}
}
fun logExperimentMetrics(
group: String,
event: String,
success: Boolean,
errorMessage: String? = null,
) {
val deviceDetails =
"Model: ${Build.MODEL}, Manufacturer: ${Build.MANUFACTURER}, Brand: ${Build.BRAND}, SDK: ${Build.VERSION.SDK_INT}"
analytics.onTranssionDeviceData(
eventValues =
mapOf(
"device_details" to deviceDetails,
"group" to group,
"event" to event,
"success" to success.toString(),
"error_message" to errorMessage.orEmpty(),
)
)
}
private fun isTranssionDevice(): Boolean =
Build.MANUFACTURER.equals("TRANSSION", ignoreCase = true) ||
Build.BRAND.equals("TRANSSION", ignoreCase = true)
}

View File

@@ -22,6 +22,7 @@ import com.navi.bbps.db.NAVI_BBPS_DATABASE_MIGRATION_7_8
import com.navi.bbps.db.NAVI_BBPS_DATABASE_MIGRATION_8_9
import com.navi.bbps.db.NAVI_BBPS_DATABASE_MIGRATION_9_10
import com.navi.bbps.db.NaviBbpsAppDatabase
import com.navi.bbps.db.TranssionDbExperiment
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@@ -34,15 +35,21 @@ import javax.inject.Singleton
object NaviBbpsDbModule {
@Singleton @Provides fun providesSharedPreferences() = BbpsSharedPreferences()
@Singleton @Provides fun providesTranssionDbExperiment() = TranssionDbExperiment()
@Singleton
@Provides
fun providesNaviBbpsAppDatabase(@ApplicationContext context: Context) =
fun providesNaviBbpsAppDatabase(
@ApplicationContext context: Context,
transsionDbExperiment: TranssionDbExperiment,
) =
Room.databaseBuilder(
context,
NaviBbpsAppDatabase::class.java,
NaviBbpsAppDatabase.NAVI_BBPS_DATABASE_NAME,
)
.enableMultiInstanceInvalidation()
.apply { transsionDbExperiment.applyDbFixes(this) }
.addMigrations(
NAVI_BBPS_DATABASE_MIGRATION_1_2,
NAVI_BBPS_DATABASE_MIGRATION_2_3,
@@ -56,7 +63,7 @@ object NaviBbpsDbModule {
NAVI_BBPS_DATABASE_MIGRATION_10_11,
NAVI_BBPS_DATABASE_MIGRATION_11_12,
)
.fallbackToDestructiveMigration()
.fallbackToDestructiveMigration(dropAllTables = false)
.build()
@Singleton