From a2c59d4469b46233bfc9b4ee63ef2ac72bb264c4 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 28 Jul 2023 16:22:30 +0200 Subject: [PATCH] Timeline: move TimelineEncryptedHistoryPostProcessor off the main thread --- libraries/matrix/impl/build.gradle.kts | 1 + .../impl/timeline/RustMatrixTimeline.kt | 1 + .../TimelineEncryptedHistoryPostProcessor.kt | 11 +++++++--- ...melineEncryptedHistoryPostProcessorTest.kt | 20 +++++++++++-------- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index 112cc0777c..499e36988c 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -45,4 +45,5 @@ dependencies { testImplementation(libs.test.junit) testImplementation(libs.test.truth) testImplementation(projects.libraries.matrix.test) + testImplementation(libs.coroutines.test) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustMatrixTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustMatrixTimeline.kt index 796b48ebb3..1a5bbf2e2a 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustMatrixTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustMatrixTimeline.kt @@ -81,6 +81,7 @@ class RustMatrixTimeline( lastLoginTimestamp = lastLoginTimestamp, isRoomEncrypted = matrixRoom.isEncrypted, paginationStateFlow = _paginationState, + dispatcher = dispatcher, ) private val timelineItemFactory = MatrixTimelineItemMapper( diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessor.kt index 0fe12e6391..b273bef21b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessor.kt @@ -19,18 +19,23 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor import io.element.android.libraries.matrix.api.timeline.MatrixTimeline import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.getAndUpdate +import kotlinx.coroutines.withContext +import timber.log.Timber import java.util.Date class TimelineEncryptedHistoryPostProcessor( + private val dispatcher: CoroutineDispatcher, private val lastLoginTimestamp: Date?, private val isRoomEncrypted: Boolean, private val paginationStateFlow: MutableStateFlow, ) { - fun process(items: List): List { - if (!isRoomEncrypted || lastLoginTimestamp == null) return items + suspend fun process(items: List): List = withContext(dispatcher) { + Timber.d("Process on Thread=${Thread.currentThread()}") + if (!isRoomEncrypted || lastLoginTimestamp == null) return@withContext items val filteredItems = replaceWithEncryptionHistoryBannerIfNeeded(items) // Disable back pagination @@ -43,7 +48,7 @@ class TimelineEncryptedHistoryPostProcessor( ) } } - return filteredItems + filteredItems } private fun replaceWithEncryptionHistoryBannerIfNeeded(list: List): List { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessorTest.kt index 91f0bc1883..3b04895bfb 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/TimelineEncryptedHistoryPostProcessorTest.kt @@ -22,6 +22,9 @@ import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem import io.element.android.libraries.matrix.test.room.anEventTimelineItem import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest import org.junit.Test import java.util.Date @@ -30,7 +33,7 @@ class TimelineEncryptedHistoryPostProcessorTest { private val defaultLastLoginTimestamp = Date(1689061264L) @Test - fun `given an unencrypted room, nothing is done`() { + fun `given an unencrypted room, nothing is done`() = runTest { val processor = createPostProcessor(isRoomEncrypted = false) val items = listOf( MatrixTimelineItem.Event(0L, anEventTimelineItem()) @@ -39,7 +42,7 @@ class TimelineEncryptedHistoryPostProcessorTest { } @Test - fun `given a null lastLoginTimestamp, nothing is done`() { + fun `given a null lastLoginTimestamp, nothing is done`() = runTest { val processor = createPostProcessor(lastLoginTimestamp = null) val items = listOf( MatrixTimelineItem.Event(0L, anEventTimelineItem()) @@ -48,14 +51,14 @@ class TimelineEncryptedHistoryPostProcessorTest { } @Test - fun `given an empty list, nothing is done`() { + fun `given an empty list, nothing is done`() = runTest { val processor = createPostProcessor() val items = emptyList() assertThat(processor.process(items)).isSameInstanceAs(items) } @Test - fun `given a list with no items before lastLoginTimestamp, nothing is done`() { + fun `given a list with no items before lastLoginTimestamp, nothing is done`() = runTest { val processor = createPostProcessor() val items = listOf( MatrixTimelineItem.Event(0L, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time + 1)) @@ -64,7 +67,7 @@ class TimelineEncryptedHistoryPostProcessorTest { } @Test - fun `given a list with an item with equal timestamp as lastLoginTimestamp, it's replaced`() { + fun `given a list with an item with equal timestamp as lastLoginTimestamp, it's replaced`() = runTest { val processor = createPostProcessor() val items = listOf( MatrixTimelineItem.Event(0L, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time)) @@ -74,7 +77,7 @@ class TimelineEncryptedHistoryPostProcessorTest { } @Test - fun `given a list with an item with a lower timestamp than lastLoginTimestamp, it's replaced`() { + fun `given a list with an item with a lower timestamp than lastLoginTimestamp, it's replaced`() = runTest { val processor = createPostProcessor() val items = listOf( MatrixTimelineItem.Event(0L, anEventTimelineItem(timestamp = defaultLastLoginTimestamp.time - 1)) @@ -85,7 +88,7 @@ class TimelineEncryptedHistoryPostProcessorTest { } @Test - fun `given a list with several with lower or equal timestamps than lastLoginTimestamp, they're replaced and the user can't back paginate`() { + fun `given a list with several with lower or equal timestamps than lastLoginTimestamp, they're replaced and the user can't back paginate`() = runTest { val paginationStateFlow = MutableStateFlow(MatrixTimeline.PaginationState(hasMoreToLoadBackwards = true, isBackPaginating = false)) val processor = createPostProcessor(paginationStateFlow = paginationStateFlow) val items = listOf( @@ -102,7 +105,7 @@ class TimelineEncryptedHistoryPostProcessorTest { assertThat(paginationStateFlow.value).isEqualTo(MatrixTimeline.PaginationState(hasMoreToLoadBackwards = false, isBackPaginating = false)) } - private fun createPostProcessor( + private fun TestScope.createPostProcessor( lastLoginTimestamp: Date? = defaultLastLoginTimestamp, isRoomEncrypted: Boolean = true, paginationStateFlow: MutableStateFlow = @@ -111,5 +114,6 @@ class TimelineEncryptedHistoryPostProcessorTest { lastLoginTimestamp = lastLoginTimestamp, isRoomEncrypted = isRoomEncrypted, paginationStateFlow = paginationStateFlow, + dispatcher = StandardTestDispatcher(testScheduler) ) }