fix(event-manager): Set initial eventId after signup/login.

This commit is contained in:
Mateusz Armatys 2024-04-09 18:48:45 +02:00 committed by MargeBot
parent a7f3b1e7bf
commit 669ea34b98
7 changed files with 174 additions and 8 deletions

View File

@ -10,16 +10,16 @@ public final class me/proton/core/eventmanager/data/BuildConfig {
}
public final class me/proton/core/eventmanager/data/CoreEventManagerStarter {
public fun <init> (Lme/proton/core/presentation/app/AppLifecycleProvider;Lme/proton/core/accountmanager/domain/AccountManager;Lme/proton/core/eventmanager/domain/EventManagerProvider;Lme/proton/core/eventmanager/domain/IsCoreEventManagerEnabled;)V
public fun <init> (Lme/proton/core/presentation/app/AppLifecycleProvider;Lme/proton/core/accountmanager/domain/AccountManager;Lme/proton/core/eventmanager/domain/EventManagerProvider;Lme/proton/core/eventmanager/domain/IsCoreEventManagerEnabled;Lme/proton/core/eventmanager/domain/repository/EventMetadataRepository;)V
public final fun start ()V
}
public final class me/proton/core/eventmanager/data/CoreEventManagerStarter_Factory : dagger/internal/Factory {
public fun <init> (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)V
public static fun create (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)Lme/proton/core/eventmanager/data/CoreEventManagerStarter_Factory;
public fun <init> (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)V
public static fun create (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)Lme/proton/core/eventmanager/data/CoreEventManagerStarter_Factory;
public synthetic fun get ()Ljava/lang/Object;
public fun get ()Lme/proton/core/eventmanager/data/CoreEventManagerStarter;
public static fun newInstance (Lme/proton/core/presentation/app/AppLifecycleProvider;Lme/proton/core/accountmanager/domain/AccountManager;Lme/proton/core/eventmanager/domain/EventManagerProvider;Lme/proton/core/eventmanager/domain/IsCoreEventManagerEnabled;)Lme/proton/core/eventmanager/data/CoreEventManagerStarter;
public static fun newInstance (Lme/proton/core/presentation/app/AppLifecycleProvider;Lme/proton/core/accountmanager/domain/AccountManager;Lme/proton/core/eventmanager/domain/EventManagerProvider;Lme/proton/core/eventmanager/domain/IsCoreEventManagerEnabled;Lme/proton/core/eventmanager/domain/repository/EventMetadataRepository;)Lme/proton/core/eventmanager/data/CoreEventManagerStarter;
}
public abstract interface class me/proton/core/eventmanager/data/EventDeserializer {
@ -390,6 +390,7 @@ public class me/proton/core/eventmanager/data/repository/EventMetadataRepository
public fun getLatestEventId (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public synthetic fun readText (Lme/proton/core/domain/entity/UniqueId;Lme/proton/core/domain/entity/UniqueId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun readText (Lme/proton/core/eventmanager/domain/EventManagerConfig;Lme/proton/core/eventmanager/domain/entity/EventId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun setInitialEventId (Lme/proton/core/eventmanager/domain/EventManagerConfig;Lme/proton/core/eventmanager/domain/entity/EventId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun update (Lme/proton/core/eventmanager/domain/entity/EventMetadata;Lme/proton/core/eventmanager/domain/entity/EventsResponse;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateEventId (Lme/proton/core/eventmanager/domain/EventManagerConfig;Lme/proton/core/eventmanager/domain/entity/EventId;Lme/proton/core/eventmanager/domain/entity/EventId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun updateMetadata (Lme/proton/core/eventmanager/domain/entity/EventMetadata;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;

View File

@ -29,8 +29,8 @@ protonBuild {
}
protonCoverage {
branchCoveragePercentage.set(60)
lineCoveragePercentage.set(79)
branchCoveragePercentage.set(62)
lineCoveragePercentage.set(81)
}
protonDagger {

View File

@ -25,6 +25,8 @@ import me.proton.core.accountmanager.presentation.onAccountReady
import me.proton.core.eventmanager.domain.EventManagerConfig
import me.proton.core.eventmanager.domain.EventManagerProvider
import me.proton.core.eventmanager.domain.IsCoreEventManagerEnabled
import me.proton.core.eventmanager.domain.entity.EventId
import me.proton.core.eventmanager.domain.repository.EventMetadataRepository
import me.proton.core.presentation.app.AppLifecycleProvider
import javax.inject.Inject
import javax.inject.Singleton
@ -34,13 +36,18 @@ class CoreEventManagerStarter @Inject constructor(
private val appLifecycleProvider: AppLifecycleProvider,
private val accountManager: AccountManager,
private val eventManagerProvider: EventManagerProvider,
private val isCoreEventManagerEnabled: IsCoreEventManagerEnabled
private val isCoreEventManagerEnabled: IsCoreEventManagerEnabled,
private val eventMetadataRepository: EventMetadataRepository
) {
private fun startOrStopReadyAccountManager() {
accountManager.observe(appLifecycleProvider.lifecycle, minActiveState = Lifecycle.State.CREATED)
.onAccountReady { account ->
val manager = eventManagerProvider.get(EventManagerConfig.Core(account.userId))
val config = EventManagerConfig.Core(account.userId)
account.details.session?.initialEventId?.let {
eventMetadataRepository.setInitialEventId(config, EventId(it))
}
val manager = eventManagerProvider.get(config)
when (isCoreEventManagerEnabled(account.userId)) {
true -> manager.start()
false -> manager.stop()

View File

@ -109,6 +109,17 @@ open class EventMetadataRepositoryImpl @Inject constructor(
nextEventId: EventId
) = eventMetadataDao.updateNextEventId(config.userId, config, eventId?.id, nextEventId.id)
override suspend fun setInitialEventId(config: EventManagerConfig, eventId: EventId) {
eventMetadataDao.insertOrIgnore(
EventMetadata(
userId = config.userId,
eventId = eventId,
config = config,
createdAt = System.currentTimeMillis()
).toEntity()
)
}
override suspend fun updateState(
config: EventManagerConfig,
state: State

View File

@ -0,0 +1,145 @@
package me.proton.core.eventmanager.data
import io.mockk.MockKAnnotations
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.mockk
import io.mockk.slot
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
import me.proton.core.account.domain.entity.Account
import me.proton.core.account.domain.entity.AccountState
import me.proton.core.account.domain.entity.SessionDetails
import me.proton.core.accountmanager.domain.AccountManager
import me.proton.core.domain.entity.UserId
import me.proton.core.eventmanager.domain.EventManager
import me.proton.core.eventmanager.domain.EventManagerConfig
import me.proton.core.eventmanager.domain.EventManagerProvider
import me.proton.core.eventmanager.domain.IsCoreEventManagerEnabled
import me.proton.core.eventmanager.domain.entity.EventId
import me.proton.core.eventmanager.domain.repository.EventMetadataRepository
import me.proton.core.presentation.app.AppLifecycleProvider
import me.proton.core.test.android.ArchTest
import me.proton.core.test.android.lifecycle.TestLifecycle
import me.proton.core.test.kotlin.CoroutinesTest
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
class CoreEventManagerStarterTest : ArchTest by ArchTest(), CoroutinesTest by CoroutinesTest() {
@MockK
private lateinit var appLifecycleProvider: AppLifecycleProvider
@MockK
private lateinit var accountManager: AccountManager
@MockK
private lateinit var eventManagerProvider: EventManagerProvider
@MockK
private lateinit var isCoreEventManagerEnabled: IsCoreEventManagerEnabled
@MockK(relaxed = true)
private lateinit var eventMetadataRepository: EventMetadataRepository
private lateinit var tested: CoreEventManagerStarter
private val testUserId = UserId("user-id")
@BeforeTest
fun setUp() {
MockKAnnotations.init(this)
tested = CoreEventManagerStarter(
appLifecycleProvider,
accountManager,
eventManagerProvider,
isCoreEventManagerEnabled,
eventMetadataRepository
)
}
@Test
fun `event loop is started`() = runTest {
// GIVEN
val account = mockReadyAccount()
val accountFlow = MutableStateFlow(account)
val eventManager = mockk<EventManager>(relaxed = true)
val lifecycleOwner = TestLifecycle()
every { accountManager.onAccountStateChanged(any()) } returns accountFlow
every { appLifecycleProvider.lifecycle } returns lifecycleOwner.lifecycle
coEvery { eventManagerProvider.get(any()) } returns eventManager
every { isCoreEventManagerEnabled(any()) } returns true
// WHEN
tested.start()
lifecycleOwner.create()
testScheduler.advanceUntilIdle()
// THEN
coVerify { eventManager.start() }
}
@Test
fun `event loop is stopped`() = runTest {
// GIVEN
val account = mockReadyAccount()
val accountFlow = MutableStateFlow(account)
val eventManager = mockk<EventManager>(relaxed = true)
val lifecycleOwner = TestLifecycle()
every { accountManager.onAccountStateChanged(any()) } returns accountFlow
every { appLifecycleProvider.lifecycle } returns lifecycleOwner.lifecycle
coEvery { eventManagerProvider.get(any()) } returns eventManager
every { isCoreEventManagerEnabled(any()) } returns false
// WHEN
tested.start()
lifecycleOwner.create()
testScheduler.advanceUntilIdle()
// THEN
coVerify { eventManager.stop() }
}
@Test
fun `initial eventId is set`() = runTest {
// GIVEN
val testEventId = EventId("event-id")
val account = mockReadyAccount(sessionDetails = mockk {
every { initialEventId } returns testEventId.id
})
val accountFlow = MutableStateFlow(account)
val eventManager = mockk<EventManager>(relaxed = true)
val lifecycleOwner = TestLifecycle()
every { accountManager.onAccountStateChanged(any()) } returns accountFlow
every { appLifecycleProvider.lifecycle } returns lifecycleOwner.lifecycle
coEvery { eventManagerProvider.get(any()) } returns eventManager
every { isCoreEventManagerEnabled(any()) } returns true
// WHEN
tested.start()
lifecycleOwner.create()
testScheduler.advanceUntilIdle()
// THEN
coVerify { eventManager.start() }
val configSlot = slot<EventManagerConfig>()
val eventIdSlot = slot<EventId>()
coVerify { eventMetadataRepository.setInitialEventId(capture(configSlot), capture(eventIdSlot)) }
assertEquals(EventManagerConfig.Core(testUserId), configSlot.captured)
assertEquals(testEventId, eventIdSlot.captured)
}
private fun mockReadyAccount(sessionDetails: SessionDetails? = null): Account = mockk<Account> {
every { details } returns mockk {
every { session } returns sessionDetails
}
every { state } returns AccountState.Ready
every { userId } returns testUserId
}
}

View File

@ -385,6 +385,7 @@ public abstract interface class me/proton/core/eventmanager/domain/repository/Ev
public abstract fun getEvents (Lme/proton/core/eventmanager/domain/EventManagerConfig;Lme/proton/core/eventmanager/domain/entity/EventId;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun getEvents (Lme/proton/core/eventmanager/domain/EventManagerConfig;Lme/proton/core/eventmanager/domain/entity/EventId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun getLatestEventId (Lme/proton/core/domain/entity/UserId;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun setInitialEventId (Lme/proton/core/eventmanager/domain/EventManagerConfig;Lme/proton/core/eventmanager/domain/entity/EventId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun update (Lme/proton/core/eventmanager/domain/entity/EventMetadata;Lme/proton/core/eventmanager/domain/entity/EventsResponse;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateEventId (Lme/proton/core/eventmanager/domain/EventManagerConfig;Lme/proton/core/eventmanager/domain/entity/EventId;Lme/proton/core/eventmanager/domain/entity/EventId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun updateMetadata (Lme/proton/core/eventmanager/domain/entity/EventMetadata;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;

View File

@ -35,6 +35,7 @@ interface EventMetadataRepository {
suspend fun updateMetadata(metadata: EventMetadata)
suspend fun updateEventId(config: EventManagerConfig, oldEventId: EventId?, newEventId: EventId)
suspend fun updateNextEventId(config: EventManagerConfig, eventId: EventId?, nextEventId: EventId)
suspend fun setInitialEventId(config: EventManagerConfig, eventId: EventId)
suspend fun updateState(config: EventManagerConfig, state: State)
suspend fun updateState(config: EventManagerConfig, eventId: EventId, state: State)
suspend fun updateRetry(config: EventManagerConfig, retry: Int)