Skip to content

Commit

Permalink
WMSDK-400: review. Added TimeProvider
Browse files Browse the repository at this point in the history
  • Loading branch information
sozinov committed Jan 24, 2025
1 parent 6462d87 commit a55a208
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 27 deletions.
2 changes: 1 addition & 1 deletion sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1247,7 +1247,7 @@ object Mindbox : MindboxLog {
@TrackVisitSource source: String? = null,
requestUrl: String? = null,
) = LoggingExceptionHandler.runCatching {
sessionStorageManager.hasSessionExpired(System.currentTimeMillis())
sessionStorageManager.hasSessionExpired()
DbManager.getConfigurations()?.endpointId?.let { endpointId ->
val applicationContext = context.applicationContext
val trackVisitData = TrackVisitData(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ internal fun DataModule(

override val inAppImageSizeStorage: InAppImageSizeStorage by lazy { InAppImageSizeStorageImpl() }

override val sessionStorageManager: SessionStorageManager by lazy { SessionStorageManager() }
override val sessionStorageManager: SessionStorageManager by lazy { SessionStorageManager(timeProvider) }

override val permissionManager: PermissionManager
get() = PermissionManagerImpl(appContext)
Expand Down Expand Up @@ -238,6 +238,9 @@ internal fun DataModule(
override val migrationManager: MigrationManager by lazy {
MigrationManager(appContext)
}
override val timeProvider: DefaultTimeProvider by lazy {
DefaultTimeProvider()
}

override val gson: Gson by lazy {
GsonBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import cloud.mindbox.mobile_sdk.monitoring.data.room.dao.MonitoringDao
import cloud.mindbox.mobile_sdk.monitoring.data.validators.MonitoringValidator
import cloud.mindbox.mobile_sdk.monitoring.domain.interfaces.*
import cloud.mindbox.mobile_sdk.network.MindboxServiceGenerator
import cloud.mindbox.mobile_sdk.utils.DefaultTimeProvider
import cloud.mindbox.mobile_sdk.utils.MigrationManager
import com.android.volley.RequestQueue
import com.google.gson.Gson
Expand Down Expand Up @@ -105,6 +106,7 @@ internal interface DataModule : MindboxModule {
val frequencyDataFiller: FrequencyDataFiller
val frequencyValidator: FrequencyValidator
val migrationManager: MigrationManager
val timeProvider: DefaultTimeProvider
}

internal interface MonitoringModule : MindboxModule {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package cloud.mindbox.mobile_sdk.inapp.data.managers

import cloud.mindbox.mobile_sdk.inapp.domain.models.*
import cloud.mindbox.mobile_sdk.logger.mindboxLogD
import cloud.mindbox.mobile_sdk.logger.mindboxLogI
import cloud.mindbox.mobile_sdk.utils.TimeProvider
import cloud.mindbox.mobile_sdk.utils.loggingRunCatching

internal class SessionStorageManager {
private typealias SessionExpirationListener = () -> Unit

internal class SessionStorageManager(private val timeProvider: TimeProvider) {

var inAppCustomerSegmentations: SegmentationCheckWrapper? = null
var unShownOperationalInApps: HashMap<String, MutableList<InApp>> = HashMap()
Expand All @@ -21,19 +24,22 @@ internal class SessionStorageManager {
var shownInAppIdsWithEvents = mutableMapOf<String, MutableSet<Int>>()
var configFetchingError: Boolean = false
var lastTrackVisitSendTime: Long = 0L
var sessionTime: Long = 0
var sessionTime: Long = 20000L

private val sessionExpirationListeners = mutableSetOf<() -> Unit>()
private val sessionExpirationListeners = mutableListOf<SessionExpirationListener>()

fun addSessionExpirationListener(listener: () -> Unit) {
fun addSessionExpirationListener(listener: SessionExpirationListener) {
sessionExpirationListeners.add(listener)
}

fun hasSessionExpired(currentTime: Long) {
fun hasSessionExpired() {
val currentTime = timeProvider.currentTimeMillis()
val timeBetweenVisits = currentTime - lastTrackVisitSendTime
val checkingSessionResultLog = when {
lastTrackVisitSendTime == 0L -> "First track visit on sdk init"

sessionTime < 0L -> "Session time is incorrect. Session time is $sessionTime ms. Skip checking session expiration"

sessionTime == 0L -> "Session time is not set. Skip checking session expiration"

timeBetweenVisits > sessionTime -> {
Expand All @@ -45,12 +51,8 @@ internal class SessionStorageManager {
"Session active. Updating lastTrackVisitSendTime. Time between trackVisits is $timeBetweenVisits ms. Session time is $sessionTime ms"
}
}
updateLastTrackTime(currentTime, checkingSessionResultLog)
}

private fun updateLastTrackTime(currentTime: Long, logMessage: String) {
lastTrackVisitSendTime = currentTime
mindboxLogD("$logMessage. New lastTrackVisitSendTime = $currentTime")
mindboxLogI("$checkingSessionResultLog. New lastTrackVisitSendTime = $currentTime")
}

private fun notifySessionExpired() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import cloud.mindbox.mobile_sdk.inapp.data.managers.SessionStorageManager
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.interactors.InAppInteractor
import cloud.mindbox.mobile_sdk.logger.MindboxLoggerImpl
import cloud.mindbox.mobile_sdk.logger.mindboxLogD
import cloud.mindbox.mobile_sdk.logger.mindboxLogI
import cloud.mindbox.mobile_sdk.monitoring.domain.interfaces.MonitoringInteractor
import cloud.mindbox.mobile_sdk.repository.MindboxPreferences
import cloud.mindbox.mobile_sdk.utils.LoggingExceptionHandler
Expand All @@ -22,7 +23,7 @@ internal class InAppMessageManagerImpl(

init {
sessionStorageManager.addSessionExpirationListener {
mindboxLogD("Session expired.Start a new session right now!")
mindboxLogI("Session expired.Start a new session right now!")
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package cloud.mindbox.mobile_sdk.utils

interface TimeProvider {
fun currentTimeMillis(): Long
}

class DefaultTimeProvider : TimeProvider {
override fun currentTimeMillis() = System.currentTimeMillis()
}
Original file line number Diff line number Diff line change
@@ -1,34 +1,47 @@
package cloud.mindbox.mobile_sdk.inapp.data.managers

import cloud.mindbox.mobile_sdk.utils.TimeProvider
import io.mockk.*
import junit.framework.TestCase.assertEquals
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test

class SessionStorageManagerTest {

private lateinit var mockTimeProvider: TimeProvider
private lateinit var sessionStorageManager: SessionStorageManager

private fun setupSessionState(
lastTrackTime: Long,
sessionTime: Long,
currentTime: Long
) {
sessionStorageManager.lastTrackVisitSendTime = lastTrackTime
sessionStorageManager.sessionTime = sessionTime
every { mockTimeProvider.currentTimeMillis() } returns currentTime
}

@Before
fun setup() {
sessionStorageManager = SessionStorageManager()
mockTimeProvider = mockk()
sessionStorageManager = SessionStorageManager(mockTimeProvider)
}

@Test
fun `hasSessionExpired should initialize lastTrackVisitSendTime on first call`() {
every { mockTimeProvider.currentTimeMillis() } returns 1000L

assertEquals(0L, sessionStorageManager.lastTrackVisitSendTime)
sessionStorageManager.hasSessionExpired(1000L)
sessionStorageManager.hasSessionExpired()
assertEquals(1000L, sessionStorageManager.lastTrackVisitSendTime)
}

@Test
fun `hasSessionExpired should not check expiration if sessionTime is 0`() {
val listener = mockk<() -> Unit>()
sessionStorageManager.addSessionExpirationListener(listener)
sessionStorageManager.sessionTime = 0L
sessionStorageManager.lastTrackVisitSendTime = 1000L
setupSessionState(lastTrackTime = 1000L, sessionTime = 0L, currentTime = 2000L)

sessionStorageManager.hasSessionExpired(2000L)
sessionStorageManager.hasSessionExpired()

verify(exactly = 0) { listener.invoke() }
assertEquals(2000L, sessionStorageManager.lastTrackVisitSendTime)
Expand All @@ -38,10 +51,9 @@ class SessionStorageManagerTest {
fun `hasSessionExpired should notify listeners when session expired`() {
val listener = mockk<() -> Unit>()
sessionStorageManager.addSessionExpirationListener(listener)
sessionStorageManager.lastTrackVisitSendTime = 1000L
sessionStorageManager.sessionTime = 999L
setupSessionState(lastTrackTime = 1000L, sessionTime = 999L, currentTime = 2000L)

sessionStorageManager.hasSessionExpired(2000L)
sessionStorageManager.hasSessionExpired()

verify(exactly = 1) { listener.invoke() }
}
Expand All @@ -50,11 +62,33 @@ class SessionStorageManagerTest {
fun `hasSessionExpired should not notify listeners when session is active`() {
val listener = mockk<() -> Unit>()
sessionStorageManager.addSessionExpirationListener(listener)
sessionStorageManager.lastTrackVisitSendTime = 1000L
sessionStorageManager.sessionTime = 2000L
setupSessionState(lastTrackTime = 1000L, sessionTime = 2000L, currentTime = 1500L)

sessionStorageManager.hasSessionExpired()

verify(exactly = 0) { listener.invoke() }
}

@Test
fun `hasSessionExpired should not notify listeners when session is active in case when sessionTime equals time between visits`() {
val listener = mockk<() -> Unit>()
sessionStorageManager.addSessionExpirationListener(listener)
setupSessionState(lastTrackTime = 1000L, sessionTime = 2000L, currentTime = 3000L)

sessionStorageManager.hasSessionExpired()

verify(exactly = 0) { listener.invoke() }
}

@Test
fun `hasSessionExpired should not notify listeners when sessionTime is negative`() {
val listener = mockk<() -> Unit>()
sessionStorageManager.addSessionExpirationListener(listener)
setupSessionState(lastTrackTime = 1000L, sessionTime = -2000L, currentTime = 1500L)

sessionStorageManager.hasSessionExpired(1500L)
sessionStorageManager.hasSessionExpired()

assertEquals(sessionStorageManager.lastTrackVisitSendTime, 1500L)
verify(exactly = 0) { listener.invoke() }
}
}

0 comments on commit a55a208

Please sign in to comment.