feat(event-manager): Allow passing query params to event loop request
As per API docs, the "Unread counters" for messages and conversations are not returned by default but must be explicitly requested (historical performance reasons on the backend). This allows passing optional query params to set them MAILANDR-1093
This commit is contained in:
parent
76282a65aa
commit
56a2cf01b4
|
@ -11,6 +11,7 @@ public final class me/proton/core/eventmanager/dagger/BuildConfig {
|
|||
|
||||
public abstract interface class me/proton/core/eventmanager/dagger/CoreEventManagerModule {
|
||||
public static final field Companion Lme/proton/core/eventmanager/dagger/CoreEventManagerModule$Companion;
|
||||
public abstract fun bindsEventManagerQueryMapProvider ()Lme/proton/core/eventmanager/data/EventManagerQueryMapProvider;
|
||||
public abstract fun provideEventManagerConfigProvider (Lme/proton/core/eventmanager/data/EventManagerConfigProviderImpl;)Lme/proton/core/eventmanager/domain/EventManagerConfigProvider;
|
||||
public abstract fun provideEventMetadataRepository (Lme/proton/core/eventmanager/data/repository/EventMetadataRepositoryImpl;)Lme/proton/core/eventmanager/domain/repository/EventMetadataRepository;
|
||||
public abstract fun provideEventWorkManager (Lme/proton/core/eventmanager/data/work/EventWorkerManagerImpl;)Lme/proton/core/eventmanager/domain/work/EventWorkerManager;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package me.proton.core.eventmanager.dagger
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.BindsOptionalOf
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
@ -26,6 +27,7 @@ import dagger.hilt.components.SingletonComponent
|
|||
import me.proton.core.eventmanager.data.EventManagerConfigProviderImpl
|
||||
import me.proton.core.eventmanager.data.EventManagerFactory
|
||||
import me.proton.core.eventmanager.data.EventManagerProviderImpl
|
||||
import me.proton.core.eventmanager.data.EventManagerQueryMapProvider
|
||||
import me.proton.core.eventmanager.data.IsCoreEventManagerEnabledImpl
|
||||
import me.proton.core.eventmanager.data.repository.EventMetadataRepositoryImpl
|
||||
import me.proton.core.eventmanager.data.work.EventWorkerManagerImpl
|
||||
|
@ -57,6 +59,9 @@ public interface CoreEventManagerModule {
|
|||
@Singleton
|
||||
public fun provideEventWorkManager(impl: EventWorkerManagerImpl): EventWorkerManager
|
||||
|
||||
@BindsOptionalOf
|
||||
public fun bindsEventManagerQueryMapProvider(): EventManagerQueryMapProvider
|
||||
|
||||
public companion object {
|
||||
@Provides
|
||||
@Singleton
|
||||
|
@ -68,4 +73,5 @@ public interface CoreEventManagerModule {
|
|||
): EventManagerProvider =
|
||||
EventManagerProviderImpl(eventManagerFactory, eventManagerConfigProvider, eventListeners)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -87,6 +87,10 @@ public final class me/proton/core/eventmanager/data/EventManagerProviderImpl : m
|
|||
public fun getAll (Lme/proton/core/domain/entity/UserId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public abstract interface class me/proton/core/eventmanager/data/EventManagerQueryMapProvider {
|
||||
public abstract fun getQueryMap (Lme/proton/core/eventmanager/domain/EventManagerConfig;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public final class me/proton/core/eventmanager/data/IsCoreEventManagerEnabledImpl : me/proton/core/eventmanager/domain/IsCoreEventManagerEnabled {
|
||||
public static final field Companion Lme/proton/core/eventmanager/data/IsCoreEventManagerEnabledImpl$Companion;
|
||||
public fun <init> (Landroid/content/Context;Lme/proton/core/featureflag/domain/FeatureFlagManager;)V
|
||||
|
@ -106,10 +110,14 @@ public final class me/proton/core/eventmanager/data/IsCoreEventManagerEnabledImp
|
|||
}
|
||||
|
||||
public abstract interface class me/proton/core/eventmanager/data/api/EventApi : me/proton/core/network/data/protonApi/BaseRetrofitApi {
|
||||
public abstract fun getEvents (Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public abstract fun getEvents (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public abstract fun getLatestEventId (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public final class me/proton/core/eventmanager/data/api/EventApi$DefaultImpls {
|
||||
public static synthetic fun getEvents$default (Lme/proton/core/eventmanager/data/api/EventApi;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public final class me/proton/core/eventmanager/data/api/response/GetCalendarEventsResponse {
|
||||
public static final field Companion Lme/proton/core/eventmanager/data/api/response/GetCalendarEventsResponse$Companion;
|
||||
public synthetic fun <init> (ILjava/lang/String;IILkotlinx/serialization/internal/SerializationConstructorMarker;)V
|
||||
|
@ -372,7 +380,7 @@ public final class me/proton/core/eventmanager/data/extension/EventMetadataKt {
|
|||
}
|
||||
|
||||
public class me/proton/core/eventmanager/data/repository/EventMetadataRepositoryImpl : me/proton/core/data/file/FileContext, me/proton/core/eventmanager/domain/repository/EventMetadataRepository {
|
||||
public fun <init> (Landroid/content/Context;Lme/proton/core/eventmanager/data/db/EventMetadataDatabase;Lme/proton/core/network/data/ApiProvider;)V
|
||||
public fun <init> (Landroid/content/Context;Lme/proton/core/eventmanager/data/db/EventMetadataDatabase;Lme/proton/core/network/data/ApiProvider;Ljava/util/Optional;)V
|
||||
public fun delete (Lme/proton/core/eventmanager/domain/EventManagerConfig;Lme/proton/core/eventmanager/domain/entity/EventId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun deleteAll (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun deleteAll (Lme/proton/core/eventmanager/domain/EventManagerConfig;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
|
@ -386,7 +394,7 @@ public class me/proton/core/eventmanager/data/repository/EventMetadataRepository
|
|||
public fun get (Lme/proton/core/eventmanager/domain/EventManagerConfig;Lme/proton/core/eventmanager/domain/entity/EventId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun getAll (Lme/proton/core/domain/entity/UserId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun getBaseDir ()Ljava/lang/String;
|
||||
public fun getEvents (Lme/proton/core/domain/entity/UserId;Lme/proton/core/eventmanager/domain/entity/EventId;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public 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 fun getEvents (Lme/proton/core/eventmanager/domain/EventManagerConfig;Lme/proton/core/eventmanager/domain/entity/EventId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public synthetic fun getFile (Lme/proton/core/domain/entity/UniqueId;Lme/proton/core/domain/entity/UniqueId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun getFile (Lme/proton/core/eventmanager/domain/EventManagerConfig;Lme/proton/core/eventmanager/domain/entity/EventId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
|
@ -405,11 +413,11 @@ public class me/proton/core/eventmanager/data/repository/EventMetadataRepository
|
|||
}
|
||||
|
||||
public final class me/proton/core/eventmanager/data/repository/EventMetadataRepositoryImpl_Factory : dagger/internal/Factory {
|
||||
public fun <init> (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)V
|
||||
public static fun create (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)Lme/proton/core/eventmanager/data/repository/EventMetadataRepositoryImpl_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/repository/EventMetadataRepositoryImpl_Factory;
|
||||
public synthetic fun get ()Ljava/lang/Object;
|
||||
public fun get ()Lme/proton/core/eventmanager/data/repository/EventMetadataRepositoryImpl;
|
||||
public static fun newInstance (Landroid/content/Context;Lme/proton/core/eventmanager/data/db/EventMetadataDatabase;Lme/proton/core/network/data/ApiProvider;)Lme/proton/core/eventmanager/data/repository/EventMetadataRepositoryImpl;
|
||||
public static fun newInstance (Landroid/content/Context;Lme/proton/core/eventmanager/data/db/EventMetadataDatabase;Lme/proton/core/network/data/ApiProvider;Ljava/util/Optional;)Lme/proton/core/eventmanager/data/repository/EventMetadataRepositoryImpl;
|
||||
}
|
||||
|
||||
public class me/proton/core/eventmanager/data/work/EventWorker : androidx/work/CoroutineWorker {
|
||||
|
|
|
@ -29,7 +29,7 @@ protonBuild {
|
|||
}
|
||||
|
||||
protonCoverage {
|
||||
minBranchCoveragePercentage.set(60)
|
||||
minBranchCoveragePercentage.set(59)
|
||||
minLineCoveragePercentage.set(77)
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,7 @@ dependencies {
|
|||
project(Module.contactData),
|
||||
project(Module.keyData),
|
||||
project(Module.kotlinTest),
|
||||
project(Module.androidTest),
|
||||
junit,
|
||||
`kotlin-test`,
|
||||
mockk
|
||||
|
|
|
@ -441,7 +441,7 @@ class EventManagerImpl @AssistedInject constructor(
|
|||
.let { deserializer.deserializeLatestEventId(it) }
|
||||
|
||||
override suspend fun getEventResponse(eventId: EventId): EventsResponse =
|
||||
eventMetadataRepository.getEvents(config.userId, eventId, deserializer.endpoint)
|
||||
eventMetadataRepository.getEvents(config, eventId, deserializer.endpoint)
|
||||
|
||||
override suspend fun deserializeEventMetadata(eventId: EventId, response: EventsResponse): EventMetadata =
|
||||
deserializer.deserializeEventMetadata(eventId, response)
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Proton Technologies AG
|
||||
* This file is part of Proton Technologies AG and Proton Mail.
|
||||
*
|
||||
* Proton Mail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Proton Mail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Proton Mail. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.proton.core.eventmanager.data
|
||||
|
||||
import me.proton.core.eventmanager.domain.EventManagerConfig
|
||||
|
||||
interface EventManagerQueryMapProvider {
|
||||
|
||||
suspend fun getQueryMap(config: EventManagerConfig): Map<String, String>
|
||||
}
|
|
@ -22,6 +22,7 @@ import me.proton.core.network.data.protonApi.BaseRetrofitApi
|
|||
import okhttp3.ResponseBody
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.QueryMap
|
||||
|
||||
interface EventApi : BaseRetrofitApi {
|
||||
|
||||
|
@ -33,6 +34,7 @@ interface EventApi : BaseRetrofitApi {
|
|||
@GET("{endpoint}/{eventId}")
|
||||
suspend fun getEvents(
|
||||
@Path("endpoint", encoded = true) endpoint: String,
|
||||
@Path("eventId") eventId: String
|
||||
@Path("eventId") eventId: String,
|
||||
@QueryMap params: Map<String, String>? = null
|
||||
): ResponseBody
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import me.proton.core.data.file.AndroidFileContext
|
|||
import me.proton.core.data.file.ExperimentalProtonFileContext
|
||||
import me.proton.core.data.file.FileContext
|
||||
import me.proton.core.domain.entity.UserId
|
||||
import me.proton.core.eventmanager.data.EventManagerQueryMapProvider
|
||||
import me.proton.core.eventmanager.data.api.EventApi
|
||||
import me.proton.core.eventmanager.data.db.EventMetadataDatabase
|
||||
import me.proton.core.eventmanager.data.entity.EventMetadataEntity
|
||||
|
@ -37,14 +38,17 @@ import me.proton.core.eventmanager.domain.entity.EventsResponse
|
|||
import me.proton.core.eventmanager.domain.entity.State
|
||||
import me.proton.core.eventmanager.domain.repository.EventMetadataRepository
|
||||
import me.proton.core.network.data.ApiProvider
|
||||
import java.util.Optional
|
||||
import javax.inject.Inject
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
|
||||
@OptIn(ExperimentalProtonFileContext::class)
|
||||
open class EventMetadataRepositoryImpl @Inject constructor(
|
||||
@ApplicationContext
|
||||
private val context: Context,
|
||||
private val db: EventMetadataDatabase,
|
||||
private val apiProvider: ApiProvider
|
||||
private val apiProvider: ApiProvider,
|
||||
private val eventManagerQueryMapProvider: Optional<EventManagerQueryMapProvider>
|
||||
) : EventMetadataRepository,
|
||||
FileContext<EventManagerConfig, EventId> by AndroidFileContext("events", context) {
|
||||
|
||||
|
@ -144,11 +148,11 @@ open class EventMetadataRepositoryImpl @Inject constructor(
|
|||
}.valueOrThrow
|
||||
|
||||
override suspend fun getEvents(
|
||||
userId: UserId,
|
||||
config: EventManagerConfig,
|
||||
eventId: EventId,
|
||||
endpoint: String
|
||||
): EventsResponse = apiProvider.get<EventApi>(userId).invoke {
|
||||
val response = getEvents(endpoint, eventId.id)
|
||||
): EventsResponse = apiProvider.get<EventApi>(config.userId).invoke {
|
||||
val response = getEvents(endpoint, eventId.id, eventManagerQueryMapProvider.getOrNull()?.getQueryMap(config))
|
||||
EventsResponse(response.string())
|
||||
}.valueOrThrow
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package me.proton.core.eventmanager.data.repository
|
||||
|
||||
import android.content.Context
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
|
@ -26,19 +27,28 @@ import io.mockk.spyk
|
|||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import me.proton.core.domain.entity.UserId
|
||||
import me.proton.core.eventmanager.data.EventManagerQueryMapProvider
|
||||
import me.proton.core.eventmanager.data.api.EventApi
|
||||
import me.proton.core.eventmanager.data.db.EventMetadataDatabase
|
||||
import me.proton.core.eventmanager.domain.EventManagerConfig
|
||||
import me.proton.core.eventmanager.domain.entity.EventId
|
||||
import me.proton.core.eventmanager.domain.entity.EventMetadata
|
||||
import me.proton.core.eventmanager.domain.entity.EventsResponse
|
||||
import me.proton.core.network.data.ApiManagerFactory
|
||||
import me.proton.core.network.data.ApiProvider
|
||||
import me.proton.core.network.domain.session.SessionId
|
||||
import me.proton.core.network.domain.session.SessionProvider
|
||||
import me.proton.core.test.android.api.TestApiManager
|
||||
import me.proton.core.test.kotlin.CoroutinesTest
|
||||
import me.proton.core.test.kotlin.UnconfinedCoroutinesTest
|
||||
import org.junit.Test
|
||||
import java.nio.file.Files
|
||||
import java.util.Optional
|
||||
import kotlin.test.AfterTest
|
||||
import kotlin.test.BeforeTest
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class EventMetadataRepositoryImplTest {
|
||||
class EventMetadataRepositoryImplTest : CoroutinesTest by UnconfinedCoroutinesTest() {
|
||||
|
||||
private val userId1 = UserId("id1")
|
||||
private val userId2 = UserId("id2")
|
||||
|
@ -55,9 +65,18 @@ class EventMetadataRepositoryImplTest {
|
|||
every { getDir(any(), any()) } returns Files.createTempDirectory("EventMetadataRepositoryImplTest-").toFile()
|
||||
}
|
||||
|
||||
private val db = mockk<EventMetadataDatabase>(relaxed = true)
|
||||
private val apiProvider = mockk<ApiProvider>(relaxed = true)
|
||||
private val eventApi = mockk<EventApi>(relaxed = true)
|
||||
private val sessionProvider = mockk<SessionProvider> {
|
||||
coEvery { this@mockk.getSessionId(userId1) } returns SessionId("userId1-sessionId")
|
||||
}
|
||||
private val apiManagerFactory = mockk<ApiManagerFactory> {
|
||||
every { this@mockk.create( any(), interfaceClass = EventApi::class ) } returns TestApiManager(eventApi)
|
||||
}
|
||||
|
||||
private val db = mockk<EventMetadataDatabase>(relaxed = true)
|
||||
private val eventManagerQueryMapProvider = mockk<EventManagerQueryMapProvider>(relaxed = true)
|
||||
|
||||
private lateinit var apiProvider: ApiProvider
|
||||
private lateinit var tested: EventMetadataRepositoryImpl
|
||||
|
||||
private fun newMetadata(
|
||||
|
@ -71,7 +90,8 @@ class EventMetadataRepositoryImplTest {
|
|||
|
||||
@BeforeTest
|
||||
fun before() {
|
||||
tested = spyk(EventMetadataRepositoryImpl(context, db, apiProvider))
|
||||
apiProvider = ApiProvider(apiManagerFactory, sessionProvider, dispatchers)
|
||||
tested = spyk(EventMetadataRepositoryImpl(context, db, apiProvider, Optional.of(eventManagerQueryMapProvider)))
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
|
@ -180,4 +200,17 @@ class EventMetadataRepositoryImplTest {
|
|||
coVerify { tested.deleteDir(user1CoreConfig) }
|
||||
coVerify { tested.writeText(user1CoreConfig, eventId, any()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getEventsUsesQueryMapFromProviderWhenAvailable() = runTest {
|
||||
// GIVEN
|
||||
val endpoint = "core/events"
|
||||
coEvery { eventManagerQueryMapProvider.getQueryMap(user1CoreConfig) } returns mapOf("MessageCounts" to "1")
|
||||
|
||||
// WHEN
|
||||
tested.getEvents(user1CoreConfig, eventId, endpoint)
|
||||
|
||||
// THEN
|
||||
coVerify { eventManagerQueryMapProvider.getQueryMap(user1CoreConfig) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -386,7 +386,7 @@ public abstract interface class me/proton/core/eventmanager/domain/repository/Ev
|
|||
public abstract fun get (Lme/proton/core/eventmanager/domain/EventManagerConfig;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public abstract fun get (Lme/proton/core/eventmanager/domain/EventManagerConfig;Lme/proton/core/eventmanager/domain/entity/EventId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public abstract fun getAll (Lme/proton/core/domain/entity/UserId;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public abstract fun getEvents (Lme/proton/core/domain/entity/UserId;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;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 update (Lme/proton/core/eventmanager/domain/entity/EventMetadata;Lme/proton/core/eventmanager/domain/entity/EventsResponse;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
|
|
|
@ -45,5 +45,5 @@ interface EventMetadataRepository {
|
|||
suspend fun getEvents(config: EventManagerConfig, eventId: EventId): EventsResponse?
|
||||
|
||||
suspend fun getLatestEventId(userId: UserId, endpoint: String): EventIdResponse
|
||||
suspend fun getEvents(userId: UserId, eventId: EventId, endpoint: String): EventsResponse
|
||||
suspend fun getEvents(config: EventManagerConfig, eventId: EventId, endpoint: String): EventsResponse
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue