Skip to content

Commit

Permalink
refactor: alter signatures on payload factory
Browse files Browse the repository at this point in the history
  • Loading branch information
fractalwrench committed Mar 12, 2024
1 parent 84ff699 commit 920c38d
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ internal class SessionModuleImpl(
}

override val payloadFactory: PayloadFactory by singleton {
PayloadFactoryImpl(payloadMessageCollator)
PayloadFactoryImpl(payloadMessageCollator, essentialServiceModule.configService)
}

private val boundaryDelegate by singleton {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.embrace.android.embracesdk.session.message

import io.embrace.android.embracesdk.payload.Session
import io.embrace.android.embracesdk.payload.SessionMessage
import io.embrace.android.embracesdk.session.lifecycle.ProcessState

/**
* Factory that creates session + background activity payloads.
Expand All @@ -11,50 +12,35 @@ internal interface PayloadFactory {
/**
* Starts a session in response to a state event.
*/
fun startSessionWithState(timestamp: Long, coldStart: Boolean): Session

/**
* Starts a session manually.
*/
fun startSessionWithManual(timestamp: Long): Session

/**
* Ends a background activity in response to a state event.
*/
fun startBackgroundActivityWithState(timestamp: Long, coldStart: Boolean): Session

/**
* Handles an uncaught exception, ending the session and saving the activity to disk.
*/
fun endBackgroundActivityWithCrash(initial: Session, timestamp: Long, crashId: String): SessionMessage

/**
* Starts a background activity in response to a state event.
*/
fun endBackgroundActivityWithState(initial: Session, timestamp: Long): SessionMessage
fun startPayloadWithState(state: ProcessState, timestamp: Long, coldStart: Boolean): Session?

/**
* Ends a session in response to a state event.
*/
fun endSessionWithState(initial: Session, timestamp: Long): SessionMessage
fun endPayloadWithState(state: ProcessState, timestamp: Long, initial: Session): SessionMessage?

/**
* Ends a session manually.
* Handles an uncaught exception, ending the session and saving the session to disk.
*/
fun endSessionWithManual(initial: Session, timestamp: Long): SessionMessage
fun endPayloadWithCrash(
state: ProcessState,
timestamp: Long,
initial: Session,
crashId: String
): SessionMessage?

/**
* Handles an uncaught exception, ending the session and saving the session to disk.
* Provides a snapshot of the active session
*/
fun endSessionWithCrash(initial: Session, timestamp: Long, crashId: String): SessionMessage
fun snapshotPayload(state: ProcessState, timestamp: Long, initial: Session): SessionMessage?

/**
* Provides a snapshot of the active session
* Starts a session manually.
*/
fun snapshotSession(initial: Session, timestamp: Long): SessionMessage?
fun startSessionWithManual(timestamp: Long): Session

/**
* Provides a snapshot of the active background activity
* Ends a session manually.
*/
fun snapshotBackgroundActivity(initial: Session, timestamp: Long): SessionMessage
fun endSessionWithManual(timestamp: Long, initial: Session): SessionMessage
}
Original file line number Diff line number Diff line change
@@ -1,35 +1,81 @@
package io.embrace.android.embracesdk.session.message

import io.embrace.android.embracesdk.config.ConfigService
import io.embrace.android.embracesdk.payload.Session
import io.embrace.android.embracesdk.payload.Session.LifeEventType
import io.embrace.android.embracesdk.payload.SessionMessage
import io.embrace.android.embracesdk.session.lifecycle.ProcessState
import io.embrace.android.embracesdk.session.orchestrator.SessionSnapshotType

internal class PayloadFactoryImpl(
private val payloadMessageCollator: PayloadMessageCollator
private val payloadMessageCollator: PayloadMessageCollator,
private val configService: ConfigService
) : PayloadFactory {

override fun startSessionWithState(timestamp: Long, coldStart: Boolean): Session {
override fun startPayloadWithState(state: ProcessState, timestamp: Long, coldStart: Boolean) =
when (state) {
ProcessState.FOREGROUND -> startSessionWithState(timestamp, coldStart)
ProcessState.BACKGROUND -> startBackgroundActivityWithState(timestamp, coldStart)
}

override fun endPayloadWithState(state: ProcessState, timestamp: Long, initial: Session) =
when (state) {
ProcessState.FOREGROUND -> endSessionWithState(initial, timestamp)
ProcessState.BACKGROUND -> endBackgroundActivityWithState(initial, timestamp)
}

override fun endPayloadWithCrash(
state: ProcessState,
timestamp: Long,
initial: Session,
crashId: String
) = when (state) {
ProcessState.FOREGROUND -> endSessionWithCrash(initial, timestamp, crashId)
ProcessState.BACKGROUND -> endBackgroundActivityWithCrash(initial, timestamp, crashId)
}

override fun snapshotPayload(state: ProcessState, timestamp: Long, initial: Session) =
when (state) {
ProcessState.FOREGROUND -> snapshotSession(initial, timestamp)
ProcessState.BACKGROUND -> snapshotBackgroundActivity(initial, timestamp)
}

override fun startSessionWithManual(timestamp: Long): Session {
return payloadMessageCollator.buildInitialSession(
InitialEnvelopeParams.SessionParams(
coldStart,
LifeEventType.STATE,
false,
LifeEventType.MANUAL,
timestamp
)
)
}

override fun startSessionWithManual(timestamp: Long): Session {
override fun endSessionWithManual(timestamp: Long, initial: Session): SessionMessage {
return payloadMessageCollator.buildFinalSessionMessage(
FinalEnvelopeParams.SessionParams(
initial = initial,
endTime = timestamp,
lifeEventType = LifeEventType.MANUAL,
endType = SessionSnapshotType.NORMAL_END
)
)
}

private fun startSessionWithState(timestamp: Long, coldStart: Boolean): Session {
return payloadMessageCollator.buildInitialSession(
InitialEnvelopeParams.SessionParams(
false,
LifeEventType.MANUAL,
coldStart,
LifeEventType.STATE,
timestamp
)
)
}

override fun startBackgroundActivityWithState(timestamp: Long, coldStart: Boolean): Session {
private fun startBackgroundActivityWithState(timestamp: Long, coldStart: Boolean): Session? {
if (!configService.isBackgroundActivityCaptureEnabled()) {
return null
}

// kept for backwards compat. the backend expects the start time to be 1 ms greater
// than the adjacent session, and manually adjusts.
val time = when {
Expand All @@ -45,7 +91,7 @@ internal class PayloadFactoryImpl(
)
}

override fun endSessionWithState(initial: Session, timestamp: Long): SessionMessage {
private fun endSessionWithState(initial: Session, timestamp: Long): SessionMessage {
return payloadMessageCollator.buildFinalSessionMessage(
FinalEnvelopeParams.SessionParams(
initial = initial,
Expand All @@ -56,18 +102,23 @@ internal class PayloadFactoryImpl(
)
}

override fun endSessionWithManual(initial: Session, timestamp: Long): SessionMessage {
return payloadMessageCollator.buildFinalSessionMessage(
FinalEnvelopeParams.SessionParams(
private fun endBackgroundActivityWithState(initial: Session, timestamp: Long): SessionMessage? {
if (!configService.isBackgroundActivityCaptureEnabled()) {
return null

Check warning on line 107 in embrace-android-sdk/src/main/java/io/embrace/android/embracesdk/session/message/PayloadFactoryImpl.kt

View check run for this annotation

Codecov / codecov/patch

embrace-android-sdk/src/main/java/io/embrace/android/embracesdk/session/message/PayloadFactoryImpl.kt#L107

Added line #L107 was not covered by tests
}

// kept for backwards compat. the backend expects the start time to be 1 ms greater
// than the adjacent session, and manually adjusts.
return payloadMessageCollator.buildFinalBackgroundActivityMessage(
FinalEnvelopeParams.BackgroundActivityParams(
initial = initial,
endTime = timestamp,
lifeEventType = LifeEventType.MANUAL,
endType = SessionSnapshotType.NORMAL_END
endTime = timestamp - 1,
lifeEventType = LifeEventType.BKGND_STATE
)
)
}

override fun endSessionWithCrash(
private fun endSessionWithCrash(
initial: Session,
timestamp: Long,
crashId: String
Expand All @@ -83,23 +134,14 @@ internal class PayloadFactoryImpl(
)
}

override fun endBackgroundActivityWithState(initial: Session, timestamp: Long): SessionMessage {
// kept for backwards compat. the backend expects the start time to be 1 ms greater
// than the adjacent session, and manually adjusts.
return payloadMessageCollator.buildFinalBackgroundActivityMessage(
FinalEnvelopeParams.BackgroundActivityParams(
initial = initial,
endTime = timestamp - 1,
lifeEventType = LifeEventType.BKGND_STATE
)
)
}

override fun endBackgroundActivityWithCrash(
private fun endBackgroundActivityWithCrash(
initial: Session,
timestamp: Long,
crashId: String
): SessionMessage {
): SessionMessage? {
if (!configService.isBackgroundActivityCaptureEnabled()) {
return null

Check warning on line 143 in embrace-android-sdk/src/main/java/io/embrace/android/embracesdk/session/message/PayloadFactoryImpl.kt

View check run for this annotation

Codecov / codecov/patch

embrace-android-sdk/src/main/java/io/embrace/android/embracesdk/session/message/PayloadFactoryImpl.kt#L143

Added line #L143 was not covered by tests
}
return payloadMessageCollator.buildFinalBackgroundActivityMessage(
FinalEnvelopeParams.BackgroundActivityParams(
initial = initial,
Expand All @@ -113,7 +155,7 @@ internal class PayloadFactoryImpl(
/**
* Called when the session is persisted every 2s to cache its state.
*/
override fun snapshotSession(initial: Session, timestamp: Long): SessionMessage {
private fun snapshotSession(initial: Session, timestamp: Long): SessionMessage {
return payloadMessageCollator.buildFinalSessionMessage(
FinalEnvelopeParams.SessionParams(
initial = initial,
Expand All @@ -124,7 +166,10 @@ internal class PayloadFactoryImpl(
)
}

override fun snapshotBackgroundActivity(initial: Session, timestamp: Long): SessionMessage {
private fun snapshotBackgroundActivity(initial: Session, timestamp: Long): SessionMessage? {
if (!configService.isBackgroundActivityCaptureEnabled()) {
return null

Check warning on line 171 in embrace-android-sdk/src/main/java/io/embrace/android/embracesdk/session/message/PayloadFactoryImpl.kt

View check run for this annotation

Codecov / codecov/patch

embrace-android-sdk/src/main/java/io/embrace/android/embracesdk/session/message/PayloadFactoryImpl.kt#L171

Added line #L171 was not covered by tests
}
return payloadMessageCollator.buildFinalBackgroundActivityMessage(
FinalEnvelopeParams.BackgroundActivityParams(
initial = initial,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import io.embrace.android.embracesdk.logging.InternalEmbraceLogger
import io.embrace.android.embracesdk.logging.InternalStaticEmbraceLogger
import io.embrace.android.embracesdk.payload.Session
import io.embrace.android.embracesdk.payload.SessionMessage
import io.embrace.android.embracesdk.session.ConfigGate
import io.embrace.android.embracesdk.session.caching.PeriodicBackgroundActivityCacher
import io.embrace.android.embracesdk.session.caching.PeriodicSessionCacher
import io.embrace.android.embracesdk.session.id.SessionIdTracker
Expand All @@ -19,7 +18,7 @@ import io.embrace.android.embracesdk.session.lifecycle.ProcessStateService
import io.embrace.android.embracesdk.session.message.PayloadFactory

internal class SessionOrchestratorImpl(
private val processStateService: ProcessStateService,
processStateService: ProcessStateService,
private val payloadFactory: PayloadFactory,
private val clock: Clock,
private val configService: ConfigService,
Expand All @@ -43,15 +42,8 @@ internal class SessionOrchestratorImpl(
else -> ProcessState.FOREGROUND
}

private val backgroundActivityGate = ConfigGate(payloadFactory) {
configService.isBackgroundActivityCaptureEnabled()
}
private val backgroundActivityFactory: PayloadFactory?
get() = backgroundActivityGate.getService()

init {
processStateService.addListener(this)
configService.addListener(backgroundActivityGate)
createInitialSession()
}

Expand All @@ -61,11 +53,7 @@ internal class SessionOrchestratorImpl(
transitionType = TransitionType.INITIAL,
timestamp = timestamp,
newSessionAction = {
if (state == ProcessState.BACKGROUND) {
backgroundActivityFactory?.startBackgroundActivityWithState(timestamp, true)
} else {
payloadFactory.startSessionWithState(timestamp, true)
}
payloadFactory.startPayloadWithState(state, timestamp, true)
}
)
}
Expand All @@ -75,10 +63,10 @@ internal class SessionOrchestratorImpl(
transitionType = TransitionType.ON_FOREGROUND,
timestamp = timestamp,
oldSessionAction = { initial: Session ->
backgroundActivityFactory?.endBackgroundActivityWithState(initial, timestamp)
payloadFactory.endPayloadWithState(ProcessState.BACKGROUND, timestamp, initial)
},
newSessionAction = {
payloadFactory.startSessionWithState(timestamp, coldStart)
payloadFactory.startPayloadWithState(ProcessState.FOREGROUND, timestamp, coldStart)
},
earlyTerminationCondition = {
return@transitionState shouldRunOnForeground(state)
Expand All @@ -91,10 +79,10 @@ internal class SessionOrchestratorImpl(
transitionType = TransitionType.ON_BACKGROUND,
timestamp = timestamp,
oldSessionAction = { initial: Session ->
payloadFactory.endSessionWithState(initial, timestamp)
payloadFactory.endPayloadWithState(ProcessState.FOREGROUND, timestamp, initial)
},
newSessionAction = {
backgroundActivityFactory?.startBackgroundActivityWithState(timestamp, false)
payloadFactory.startPayloadWithState(ProcessState.BACKGROUND, timestamp, false)
},
earlyTerminationCondition = {
return@transitionState shouldRunOnBackground(state)
Expand All @@ -109,7 +97,7 @@ internal class SessionOrchestratorImpl(
timestamp = timestamp,
clearUserInfo = clearUserInfo,
oldSessionAction = { initial: Session ->
payloadFactory.endSessionWithManual(initial, timestamp)
payloadFactory.endSessionWithManual(timestamp, initial)
},
newSessionAction = {
payloadFactory.startSessionWithManual(timestamp)
Expand All @@ -131,23 +119,15 @@ internal class SessionOrchestratorImpl(
transitionType = TransitionType.CRASH,
timestamp = timestamp,
oldSessionAction = { initial: Session ->
if (processStateService.isInBackground) {
backgroundActivityFactory?.endBackgroundActivityWithCrash(
initial,
timestamp,
crashId
)
} else {
payloadFactory.endSessionWithCrash(initial, timestamp, crashId)
}
payloadFactory.endPayloadWithCrash(state, timestamp, initial, crashId)
}
)
}

override fun reportBackgroundActivityStateChange() {
if (state == ProcessState.BACKGROUND) {
val initial = activeSession ?: return
scheduleBackgroundActivitySave(initial)
scheduleBackgroundActivitySave(ProcessState.BACKGROUND, initial)
}
}

Expand Down Expand Up @@ -254,20 +234,20 @@ internal class SessionOrchestratorImpl(
ProcessState.FOREGROUND -> {
periodicSessionCacher.start {
synchronized(lock) {
payloadFactory.snapshotSession(newState, clock.now())?.apply {
payloadFactory.snapshotPayload(endProcessState, clock.now(), newState)?.apply {
deliveryService.sendSession(this, SessionSnapshotType.PERIODIC_CACHE)
}
}
}
}
ProcessState.BACKGROUND -> scheduleBackgroundActivitySave(newState)
ProcessState.BACKGROUND -> scheduleBackgroundActivitySave(endProcessState, newState)
}
}

private fun scheduleBackgroundActivitySave(initial: Session) {
private fun scheduleBackgroundActivitySave(endProcessState: ProcessState, initial: Session) {
periodicBackgroundActivityCacher.scheduleSave {
synchronized(lock) {
backgroundActivityFactory?.snapshotBackgroundActivity(initial, clock.now())?.apply {
payloadFactory.snapshotPayload(endProcessState, clock.now(), initial)?.apply {
deliveryService.sendSession(this, SessionSnapshotType.PERIODIC_CACHE)
}
}
Expand Down

0 comments on commit 920c38d

Please sign in to comment.