Skip to content

Commit

Permalink
refactor: move active session down
Browse files Browse the repository at this point in the history
  • Loading branch information
fractalwrench committed Nov 20, 2023
1 parent e724ccd commit 1ce5fe5
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 190 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,6 @@ internal class EmbraceSessionService(
const val SESSION_CACHING_INTERVAL = 2
}

/**
* The currently active session.
*/
@Volatile
internal var activeSession: Session? = null

init {
if (!this.processStateService.isInBackground) {
// If the app goes to foreground before the SDK finishes its startup,
Expand All @@ -57,7 +51,7 @@ internal class EmbraceSessionService(
}

// Send any sessions that were cached and not yet sent.
deliveryService.sendCachedSessions(isNdkEnabled, ndkService, activeSession?.sessionId)
deliveryService.sendCachedSessions(isNdkEnabled, ndkService, sessionHandler.getSessionId())
}

override fun startSession(coldStart: Boolean, startType: Session.SessionLifeEventType, startTime: Long) {
Expand All @@ -80,23 +74,17 @@ internal class EmbraceSessionService(

if (sessionMessage != null) {
logger.logDeveloper(TAG, "Session Message is created")
activeSession = sessionMessage.session
logger.logDeveloper(TAG, "Active session: " + activeSession?.sessionId)
} else {
logger.logDeveloper(TAG, "Session Message is NULL")
}
}

override fun handleCrash(crashId: String) {
logger.logDeveloper(TAG, "Attempt to handle crash id: $crashId")

activeSession?.also {
sessionHandler.onCrash(
it,
crashId,
spansService.flushSpans(EmbraceAttributes.AppTerminationCause.CRASH)
)
} ?: logger.logDeveloper(TAG, "Active session is NULL")
sessionHandler.onCrash(
crashId,
spansService.flushSpans(EmbraceAttributes.AppTerminationCause.CRASH)
)
}

/**
Expand All @@ -105,11 +93,7 @@ internal class EmbraceSessionService(

fun onPeriodicCacheActiveSession() {
try {
val session = activeSession ?: return
sessionHandler.onPeriodicCacheActiveSession(
session,
spansService.completedSpans()
)
sessionHandler.onPeriodicCacheActiveSession(spansService.completedSpans())
} catch (ex: Exception) {
logger.logDebug("Error while caching active session", ex)
}
Expand Down Expand Up @@ -163,16 +147,11 @@ internal class EmbraceSessionService(
*/
private fun endSession(endType: Session.SessionLifeEventType, endTime: Long) {
logger.logDebug("Will try to end session.")
val session = activeSession ?: return
sessionHandler.onSessionEnded(
endType,
session,
endTime,
spansService.flushSpans()
)

// clear active session
activeSession = null
logger.logDeveloper(TAG, "Active session cleared")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ internal class SessionHandler(
private val sessionPeriodicCacheExecutorService: ScheduledExecutorService
) : Closeable {

/**
* The currently active session.
*/
@Volatile
private var activeSession: Session? = null

internal fun getSessionId(): String? = activeSession?.sessionId

var scheduledFuture: ScheduledFuture<*>? = null

/**
Expand Down Expand Up @@ -86,6 +94,7 @@ internal class SessionHandler(
userService.loadUserInfoFromDisk(),
sessionProperties.get()
)
activeSession = session
logDeveloper("SessionHandler", "SessionId = ${session.sessionId}")

// Record the connection type at the start of the session.
Expand Down Expand Up @@ -114,15 +123,16 @@ internal class SessionHandler(
*/
fun onSessionEnded(
endType: SessionLifeEventType,
originSession: Session,
endTime: Long,
completedSpans: List<EmbraceSpanData>? = null
) {
synchronized(lock) {
val session = activeSession ?: return

logger.logDebug("Will try to run end session full.")
val fullEndSessionMessage = createSessionSnapshot(
SessionSnapshotType.NORMAL_END,
originSession,
session,
sessionProperties,
completedSpans,
endType,
Expand All @@ -131,11 +141,14 @@ internal class SessionHandler(

// Clean every collection of those services which have collections in memory.
memoryCleanerService.cleanServicesCollections(exceptionService)
metadataService.removeActiveSessionId(originSession.sessionId)
metadataService.removeActiveSessionId(session.sessionId)
logger.logDebug("Services collections successfully cleaned.")
sessionProperties.clearTemporary()
logger.logDebug("Session properties successfully temporary cleared.")
deliveryService.sendSession(fullEndSessionMessage, SessionMessageState.END)

// clear active session
activeSession = null
}
}

Expand All @@ -144,15 +157,15 @@ internal class SessionHandler(
* and send it to our servers.
*/
fun onCrash(
originSession: Session,
crashId: String,
completedSpans: List<EmbraceSpanData>? = null
) {
synchronized(lock) {
val session = activeSession ?: return
logger.logDebug("Will try to run end session for crash.")
val fullEndSessionMessage = createSessionSnapshot(
SessionSnapshotType.JVM_CRASH,
originSession,
session,
sessionProperties,
completedSpans,
SessionLifeEventType.STATE,
Expand All @@ -170,21 +183,19 @@ internal class SessionHandler(
* Note that the session message will not be sent to our servers.
*/
fun onPeriodicCacheActiveSession(
activeSession: Session?,
completedSpans: List<EmbraceSpanData>? = null
): SessionMessage? {
synchronized(lock) {
val msg = activeSession?.let {
logger.logDebug("Will try to run end session for caching.")
createSessionSnapshot(
SessionSnapshotType.PERIODIC_CACHE,
activeSession,
sessionProperties,
completedSpans,
SessionLifeEventType.STATE,
clock.now()
)
}
logger.logDebug("Will try to run end session for caching.")
val session = activeSession ?: return null
val msg = createSessionSnapshot(
SessionSnapshotType.PERIODIC_CACHE,
session,
sessionProperties,
completedSpans,
SessionLifeEventType.STATE,
clock.now()
)
msg?.let(deliveryService::saveSession)
return msg
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import io.embrace.android.embracesdk.ndk.NdkService
import io.embrace.android.embracesdk.payload.Session
import io.embrace.android.embracesdk.payload.Session.SessionLifeEventType
import io.embrace.android.embracesdk.payload.SessionMessage
import io.mockk.Called
import io.mockk.clearAllMocks
import io.mockk.every
import io.mockk.mockk
Expand All @@ -24,6 +23,7 @@ import org.junit.AfterClass
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
Expand Down Expand Up @@ -93,68 +93,6 @@ internal class EmbraceSessionServiceTest {
}
}

@Test
fun `start session successfully`() {
initializeSessionService()
val coldStart = /* same for false */ true
val type = /* could be any type */ SessionLifeEventType.STATE
every {
mockSessionHandler.onSessionStarted(
coldStart,
type,
any(),
any(),
any()
)
} returns mockSessionMessage

val startTime = clock.now()

service.startSession(coldStart, type, startTime)

assertEquals(mockSession, service.activeSession)
verify {
mockSessionHandler.onSessionStarted(
coldStart,
type,
startTime,
any(),
any()
)
}
assertEquals(mockSession, service.activeSession)
}

@Test
fun `start session if not allowed then session handler will return a null session`() {
initializeSessionService()
val coldStart = /* same for false */ true
val type = /* could be any type */ SessionLifeEventType.STATE
every {
mockSessionHandler.onSessionStarted(
coldStart,
type,
any(),
any(),
any()
)
} returns null

val startTime = clock.now()
service.startSession(coldStart, type, startTime)

assertNull(service.activeSession)
verify {
mockSessionHandler.onSessionStarted(
coldStart,
type,
startTime,
any(),
any()
)
}
}

@Test
fun `handle crash successfully`() {
initializeSessionService()
Expand All @@ -174,7 +112,7 @@ internal class EmbraceSessionServiceTest {

service.handleCrash(crashId)

verify { mockSessionHandler.onCrash(mockSession, crashId) }
verify { mockSessionHandler.onCrash(crashId) }
}

@Test
Expand All @@ -184,7 +122,7 @@ internal class EmbraceSessionServiceTest {
val startTime = 123L

service.onForeground(coldStart, startTime, 456)
assertNull(deliveryService.lastSentCachedSession)
assertEquals("", deliveryService.lastSentCachedSession)

// verify that a STATE session is started
verify {
Expand Down Expand Up @@ -218,26 +156,6 @@ internal class EmbraceSessionServiceTest {
}
}

@Test
fun `on background ends a state session for a previously existing session`() {
initializeSessionService()
// let's start session first so we have an active session
startDefaultSession()

service.onBackground(456)

// verify session is ended
verify {
mockSessionHandler.onSessionEnded(
SessionLifeEventType.STATE,
mockSession,
456
)
}
// verify active session has been reset
assertNull(service.activeSession)
}

@Test
fun `trigger stateless end session successfully for activity in background`() {
initializeSessionService()
Expand All @@ -250,7 +168,6 @@ internal class EmbraceSessionServiceTest {
verify {
mockSessionHandler.onSessionEnded(
SessionLifeEventType.MANUAL,
mockSession,
0,
any()
)
Expand All @@ -267,7 +184,7 @@ internal class EmbraceSessionServiceTest {
service.triggerStatelessSessionEnd(endType)

// verify session is ended
verify { mockSessionHandler.onSessionEnded(endType, mockSession, 0, any()) }
verify { mockSessionHandler.onSessionEnded(endType, 0, any()) }
// verify that a MANUAL session is started
verify {
mockSessionHandler.onSessionStarted(
Expand All @@ -284,8 +201,7 @@ internal class EmbraceSessionServiceTest {
fun `trigger stateless end session for a STATE session end type should not do anything`() {
initializeSessionService()
service.triggerStatelessSessionEnd(SessionLifeEventType.STATE)

verify { mockSessionHandler wasNot Called }
assertTrue(deliveryService.lastSentSessions.isEmpty())
}

@Test
Expand Down Expand Up @@ -324,7 +240,6 @@ internal class EmbraceSessionServiceTest {
verify {
mockSessionHandler.onSessionEnded(
endType = any(),
originSession = any(),
endTime = any(),
completedSpans = match {
it.size == 2
Expand All @@ -348,7 +263,6 @@ internal class EmbraceSessionServiceTest {
verify {
mockSessionHandler.onSessionEnded(
endType = any(),
originSession = any(),
endTime = any(),
completedSpans = match {
it.size == 2
Expand All @@ -371,7 +285,6 @@ internal class EmbraceSessionServiceTest {
// expect 2 spans to be flushed: session span and sdk init span
verify {
mockSessionHandler.onCrash(
originSession = any(),
crashId = any(),
completedSpans = match {
it.size == 2
Expand Down
Loading

0 comments on commit 1ce5fe5

Please sign in to comment.