timeline : add synchronisation around timelineItemIndexer

This commit is contained in:
ganfra 2024-10-02 17:52:06 +02:00
parent aed5280c63
commit 7780bd7e11
2 changed files with 23 additions and 8 deletions

View file

@ -11,26 +11,39 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.di.SingleIn import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@SingleIn(RoomScope::class) @SingleIn(RoomScope::class)
class TimelineItemIndexer @Inject constructor() { class TimelineItemIndexer @Inject constructor() {
// This is a latch to wait for the first process call
private val firstProcessLatch = CompletableDeferred<Unit>()
private val timelineEventsIndexes = mutableMapOf<EventId, Int>() private val timelineEventsIndexes = mutableMapOf<EventId, Int>()
fun isKnown(eventId: EventId): Boolean { private val mutex = Mutex()
return timelineEventsIndexes.containsKey(eventId).also {
Timber.d("$eventId isKnown = $it") suspend fun isKnown(eventId: EventId): Boolean {
firstProcessLatch.await()
return mutex.withLock {
timelineEventsIndexes.containsKey(eventId).also {
Timber.d("$eventId isKnown = $it")
}
} }
} }
fun indexOf(eventId: EventId): Int { suspend fun indexOf(eventId: EventId): Int {
return (timelineEventsIndexes[eventId] ?: -1).also { firstProcessLatch.await()
Timber.d("indexOf $eventId= $it") return mutex.withLock {
(timelineEventsIndexes[eventId] ?: -1).also {
Timber.d("indexOf $eventId= $it")
}
} }
} }
fun process(timelineItems: List<TimelineItem>) { suspend fun process(timelineItems: List<TimelineItem>) = mutex.withLock {
Timber.d("process ${timelineItems.size} items") Timber.d("process ${timelineItems.size} items")
timelineEventsIndexes.clear() timelineEventsIndexes.clear()
timelineItems.forEachIndexed { index, timelineItem -> timelineItems.forEachIndexed { index, timelineItem ->
@ -46,6 +59,7 @@ class TimelineItemIndexer @Inject constructor() {
else -> Unit else -> Unit
} }
} }
firstProcessLatch.complete(Unit)
} }
private fun processEvent(event: TimelineItem.Event, index: Int) { private fun processEvent(event: TimelineItem.Event, index: Int) {

View file

@ -13,11 +13,12 @@ import io.element.android.features.messages.impl.timeline.model.virtual.Timeline
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.AN_EVENT_ID
import kotlinx.coroutines.test.runTest
import org.junit.Test import org.junit.Test
class TimelineItemIndexerTest { class TimelineItemIndexerTest {
@Test @Test
fun `test TimelineItemIndexer`() { fun `test TimelineItemIndexer`() = runTest {
val eventIds = mutableListOf<EventId>() val eventIds = mutableListOf<EventId>()
val data = listOf( val data = listOf(
aTimelineItemEvent().also { eventIds.add(it.eventId!!) }, aTimelineItemEvent().also { eventIds.add(it.eventId!!) },