From 676973b02096ea33e0eedd47c2829975c39c3d0b Mon Sep 17 00:00:00 2001 From: Themis wang Date: Wed, 16 Apr 2025 13:49:44 -0400 Subject: [PATCH] ackground time nullable --- .../google/firebase/sessions/SessionData.kt | 11 +++---- .../sessions/SharedSessionRepository.kt | 16 ++++++---- .../sessions/SharedSessionRepositoryTest.kt | 32 ++++++++++++------- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/firebase-sessions/src/main/kotlin/com/google/firebase/sessions/SessionData.kt b/firebase-sessions/src/main/kotlin/com/google/firebase/sessions/SessionData.kt index 3eaf1a6c011..84e05b89ed9 100644 --- a/firebase-sessions/src/main/kotlin/com/google/firebase/sessions/SessionData.kt +++ b/firebase-sessions/src/main/kotlin/com/google/firebase/sessions/SessionData.kt @@ -27,7 +27,10 @@ import kotlinx.serialization.json.Json /** Session data to be persisted. */ @Serializable -internal data class SessionData(val sessionDetails: SessionDetails, val backgroundTime: Time) +internal data class SessionData( + val sessionDetails: SessionDetails, + val backgroundTime: Time? = null +) /** DataStore json [Serializer] for [SessionData]. */ @Singleton @@ -38,11 +41,7 @@ constructor( private val timeProvider: TimeProvider, ) : Serializer { override val defaultValue: SessionData - get() = - SessionData( - sessionDetails = sessionGenerator.generateNewSession(currentSession = null), - backgroundTime = timeProvider.currentTime(), - ) + get() = SessionData(sessionGenerator.generateNewSession(currentSession = null)) override suspend fun readFrom(input: InputStream): SessionData = try { diff --git a/firebase-sessions/src/main/kotlin/com/google/firebase/sessions/SharedSessionRepository.kt b/firebase-sessions/src/main/kotlin/com/google/firebase/sessions/SharedSessionRepository.kt index 7c25ab7f8c0..5606342a428 100644 --- a/firebase-sessions/src/main/kotlin/com/google/firebase/sessions/SharedSessionRepository.kt +++ b/firebase-sessions/src/main/kotlin/com/google/firebase/sessions/SharedSessionRepository.kt @@ -62,14 +62,13 @@ constructor( internal var previousNotificationType: NotificationType = NotificationType.GENERAL init { - println("session repo init") CoroutineScope(backgroundDispatcher).launch { sessionDataStore.data .catch { val newSession = SessionData( sessionDetails = sessionGenerator.generateNewSession(null), - backgroundTime = timeProvider.currentTime() + backgroundTime = null ) Log.d( TAG, @@ -123,7 +122,7 @@ constructor( val newSessionDetails = sessionGenerator.generateNewSession(sessionData.sessionDetails) sessionFirelogPublisher.mayLogSession(sessionDetails = newSessionDetails) - currentSessionData.copy(sessionDetails = newSessionDetails) + currentSessionData.copy(sessionDetails = newSessionDetails, backgroundTime = null) } else { currentSessionData } @@ -131,7 +130,8 @@ constructor( } catch (ex: Exception) { Log.d(TAG, "App appForegrounded, failed to update data. Message: ${ex.message}") val newSessionDetails = sessionGenerator.generateNewSession(sessionData.sessionDetails) - localSessionData = localSessionData.copy(sessionDetails = newSessionDetails) + localSessionData = + localSessionData.copy(sessionDetails = newSessionDetails, backgroundTime = null) sessionFirelogPublisher.mayLogSession(sessionDetails = newSessionDetails) val sessionId = newSessionDetails.sessionId @@ -159,8 +159,12 @@ constructor( } private fun shouldInitiateNewSession(sessionData: SessionData): Boolean { - val interval = timeProvider.currentTime() - sessionData.backgroundTime - return interval > sessionsSettings.sessionRestartTimeout + sessionData.backgroundTime?.let { + val interval = timeProvider.currentTime() - it + return interval > sessionsSettings.sessionRestartTimeout + } + Log.d(TAG, "No process has backgrounded yet, should not change the session.") + return false } private companion object { diff --git a/firebase-sessions/src/test/kotlin/com/google/firebase/sessions/SharedSessionRepositoryTest.kt b/firebase-sessions/src/test/kotlin/com/google/firebase/sessions/SharedSessionRepositoryTest.kt index 301f748f05a..135b8df4f22 100644 --- a/firebase-sessions/src/test/kotlin/com/google/firebase/sessions/SharedSessionRepositoryTest.kt +++ b/firebase-sessions/src/test/kotlin/com/google/firebase/sessions/SharedSessionRepositoryTest.kt @@ -33,7 +33,6 @@ import com.google.firebase.sessions.testing.FakeUuidGenerator import kotlin.time.Duration.Companion.hours import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.asCoroutineDispatcher -import kotlinx.coroutines.launch import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.After @@ -135,7 +134,7 @@ class SharedSessionRepositoryTest { } @Test - fun appForegroundSharedSessionRepo_updateSuccess() = runTest { + fun appForegroundGenerateNewSession_updateSuccess() = runTest { val sessionFirelogPublisher = SessionFirelogPublisherImpl( fakeFirebaseApp.firebaseApp, @@ -166,20 +165,22 @@ class SharedSessionRepositoryTest { backgroundDispatcher = TestOnlyExecutors.background().asCoroutineDispatcher() + coroutineContext ) - backgroundScope.launch { - fakeTimeProvider.addInterval(20.hours) - sharedSessionRepository.appForeground() - } runCurrent() + + fakeTimeProvider.addInterval(20.hours) + sharedSessionRepository.appForeground() + runCurrent() + assertThat(sharedSessionRepository.localSessionData.sessionDetails.sessionId) .isEqualTo(SESSION_ID_1) + assertThat(sharedSessionRepository.localSessionData.backgroundTime).isNull() assertThat(sharedSessionRepository.previousNotificationType) .isEqualTo(SharedSessionRepositoryImpl.NotificationType.GENERAL) fakeDataStore.close() } @Test - fun appForegroundSharedSessionRepo_updateFail() = runTest { + fun appForegroundGenerateNewSession_updateFail() = runTest { val sessionFirelogPublisher = SessionFirelogPublisherImpl( fakeFirebaseApp.firebaseApp, @@ -201,7 +202,6 @@ class SharedSessionRepositoryTest { ), IllegalArgumentException("Datastore init failed") ) - fakeDataStore.throwOnNextUpdateData(IllegalArgumentException("Datastore update failed")) val sharedSessionRepository = SharedSessionRepositoryImpl( sessionsSettings, @@ -212,15 +212,23 @@ class SharedSessionRepositoryTest { backgroundDispatcher = TestOnlyExecutors.background().asCoroutineDispatcher() + coroutineContext ) + runCurrent() - backgroundScope.launch { - fakeTimeProvider.addInterval(20.hours) - sharedSessionRepository.appForeground() - } + // set background time first + fakeDataStore.throwOnNextUpdateData(IllegalArgumentException("Datastore update failed")) + sharedSessionRepository.appBackground() runCurrent() + + // foreground update session + fakeTimeProvider.addInterval(20.hours) + fakeDataStore.throwOnNextUpdateData(IllegalArgumentException("Datastore update failed")) + sharedSessionRepository.appForeground() + runCurrent() + // session_2 here because session_1 is failed when try to init datastore assertThat(sharedSessionRepository.localSessionData.sessionDetails.sessionId) .isEqualTo(SESSION_ID_2) + assertThat(sharedSessionRepository.localSessionData.backgroundTime).isNull() assertThat(sharedSessionRepository.previousNotificationType) .isEqualTo(SharedSessionRepositoryImpl.NotificationType.FALLBACK) fakeDataStore.close()