Coverage Summary for Class: DbManager (cloud.mindbox.mobile_sdk.managers)

Class Method, % Branch, % Line, % Instruction, %
DbManager 15.4% (2/13) 0% (0/6) 13% (3/23) 11.9% (18/151)
DbManager$addEventToQueue$1 100% (1/1) 50% (1/2) 85.7% (6/7) 60% (21/35)
DbManager$getConfigurations$1 100% (1/1) 50% (1/2) 100% (3/3) 85.7% (18/21)
DbManager$getEvents$1 0% (0/1) 0% (0/1) 0% (0/25)
DbManager$getFilteredEvents$1 0% (0/1) 0% (0/2) 0% (0/5) 0% (0/33)
DbManager$getFilteredEvents$1$1 0% (0/1) 0% (0/1) 0% (0/15)
DbManager$getFilteredEvents$1$invoke$$inlined$sortedBy$1 0% (0/1)
DbManager$init$1 0% (0/1) 0% (0/2) 0% (0/2) 0% (0/9)
DbManager$isTooOld$1 0% (0/1) 0% (0/2) 0% (0/1) 0% (0/13)
DbManager$removeEventFromQueue$1 0% (0/1) 0% (0/2) 0% (0/5) 0% (0/52)
DbManager$removeEventsFromQueue$1 0% (0/1) 0% (0/2) 0% (0/3) 0% (0/47)
DbManager$saveConfigurations$1 0% (0/1) 0% (0/2) 0% (0/5) 0% (0/19)
Total 16.7% (4/24) 9.1% (2/22) 21.4% (12/56) 13.6% (57/420)


 package cloud.mindbox.mobile_sdk.managers
 
 import android.content.Context
 import cloud.mindbox.mobile_sdk.logger.MindboxLoggerImpl
 import cloud.mindbox.mobile_sdk.models.Configuration
 import cloud.mindbox.mobile_sdk.models.Event
 import cloud.mindbox.mobile_sdk.repository.MindboxDatabase
 import cloud.mindbox.mobile_sdk.services.BackgroundWorkManager
 import cloud.mindbox.mobile_sdk.utils.LoggingExceptionHandler
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.launch
 
 internal object DbManager {
 
     const val EVENTS_TABLE_NAME = "mindbox_events_table"
     const val CONFIGURATION_TABLE_NAME = "mindbox_configuration_table"
 
     private const val MAX_EVENT_LIST_SIZE = 10000
     private const val HALF_YEAR_IN_MILLISECONDS: Long = 15552000000L
     private const val DELAY_FOR_SEND_IN_BACKGROUND = 120_000
 
     @Volatile
     private lateinit var mindboxDb: MindboxDatabase
 
     fun init(context: Context) = LoggingExceptionHandler.runCatching {
         if (!this::mindboxDb.isInitialized) {
             mindboxDb = MindboxDatabase.getInstance(context)
         }
     }
 
     fun addEventToQueue(context: Context, event: Event) = LoggingExceptionHandler.runCatching {
         try {
             mindboxDb.eventsDao().insert(event)
             MindboxLoggerImpl.d(this, "Event ${event.eventType.operation} was added to queue")
         } catch (exception: RuntimeException) {
             MindboxLoggerImpl.e(
                 this,
                 "Error writing object to the database: ${event.body}",
                 exception,
             )
         }
 
         BackgroundWorkManager.startOneTimeService(context)
     }
 
     fun getFilteredEvents(): List<Event> = LoggingExceptionHandler.runCatching(
         defaultValue = listOf(),
     ) {
         val events = getEvents().sortedBy(Event::enqueueTimestamp)
         val resultEvents = filterEvents(events)
 
         if (events.size > resultEvents.size) {
             CoroutineScope(Dispatchers.IO).launch { removeEventsFromQueue(events - resultEvents) }
         }
 
         resultEvents
     }
 
     fun getFilteredEventsForBackgroundSend() = System.currentTimeMillis().let { time ->
         getFilteredEvents().filter { time - it.enqueueTimestamp > DELAY_FOR_SEND_IN_BACKGROUND }
     }
 
     fun removeEventFromQueue(event: Event) = LoggingExceptionHandler.runCatching {
         try {
             synchronized(this) { mindboxDb.eventsDao().delete(event.transactionId) }
             MindboxLoggerImpl.d(
                 this,
                 "Event ${event.eventType.operation};${event.transactionId} was deleted from queue",
             )
         } catch (exception: RuntimeException) {
             MindboxLoggerImpl.e(this, "Error deleting item from database", exception)
         }
     }
 
     private fun removeEventsFromQueue(events: List<Event>) = LoggingExceptionHandler.runCatching {
         try {
             synchronized(this) { mindboxDb.eventsDao().deleteEvents(events) }
             MindboxLoggerImpl.d(this, "${events.size} events were deleted from queue")
         } catch (exception: RuntimeException) {
             MindboxLoggerImpl.e(this, "Error deleting items from database", exception)
         }
     }
 
     fun saveConfigurations(configuration: Configuration) = LoggingExceptionHandler.runCatching {
         try {
             mindboxDb.configurationDao().insert(configuration)
         } catch (exception: RuntimeException) {
             MindboxLoggerImpl.e(
                 this,
                 "Error writing object configuration to the database",
                 exception,
             )
         }
     }
 
     fun getConfigurations(): Configuration? = LoggingExceptionHandler.runCatching(
         defaultValue = null,
     ) {
         try {
             mindboxDb.configurationDao().get()
         } catch (exception: RuntimeException) {
             // invalid data in case of exception
             MindboxLoggerImpl.e(this, "Error reading from database", exception)
             null
         }
     }
 
     fun listenConfigurations(): Flow<Configuration> {
         return try {
             mindboxDb.configurationDao().listenConfiguration()
         } catch (e: RuntimeException) {
             MindboxLoggerImpl.e(this, "Error reading from database", e)
             flowOf(null)
         }.filterNotNull()
     }
 
     private fun getEvents(): List<Event> = LoggingExceptionHandler.runCatching(
         defaultValue = listOf(),
     ) {
         synchronized(this) { mindboxDb.eventsDao().getAll() }
     }
 
     fun removeAllEventsFromQueue() {
         try {
             mindboxDb.eventsDao().deleteAll()
         } catch (exception: RuntimeException) {
             // invalid data in case of exception
             MindboxLoggerImpl.e(this, "Error reading from database", exception)
         }
     }
 
     private fun filterEvents(events: List<Event>): List<Event> {
         val time = System.currentTimeMillis()
         val filteredEvents = events.filterNot { it.isTooOld(time) }
 
         return filteredEvents.takeLast(MAX_EVENT_LIST_SIZE)
     }
 
     private fun Event.isTooOld(
         timeNow: Long,
     ): Boolean = LoggingExceptionHandler.runCatching(defaultValue = false) {
         timeNow - this.enqueueTimestamp >= HALF_YEAR_IN_MILLISECONDS
     }
 }