From fa64db56e744a8d67ad46bc1727cb67213851388 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 19 Sep 2025 16:24:06 +0200 Subject: [PATCH] Add logs to detect duplicates in the room list (#5364) * Add logs to detect duplicates in the room list * Add comments and helper class about the caching results logging --- .../impl/datasource/RoomListDataSource.kt | 34 ++++++++++++++++++- .../impl/roomlist/RoomSummaryListProcessor.kt | 6 ++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSource.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSource.kt index 28f7f95908..b9e8d27bf7 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSource.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListDataSource.kt @@ -30,6 +30,7 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext +import timber.log.Timber import kotlin.time.Duration.Companion.seconds @Inject @@ -102,13 +103,44 @@ class RoomListDataSource( } private suspend fun buildAndEmitAllRooms(roomSummaries: List, useCache: Boolean = true) { + // Used to detect duplicates in the room list summaries - see comment below + data class CacheResult(val index: Int, val fromCache: Boolean) + val cachingResults = mutableMapOf>() + val roomListRoomSummaries = diffCache.indices().mapNotNull { index -> if (useCache) { - diffCache.get(index) ?: buildAndCacheItem(roomSummaries, index) + diffCache.get(index)?.let { cachedItem -> + // Add the cached item to the caching results + val pairs = cachingResults.getOrDefault(cachedItem.roomId, mutableListOf()) + pairs.add(CacheResult(index, fromCache = true)) + cachingResults[cachedItem.roomId] = pairs + cachedItem + } ?: run { + roomSummaries.getOrNull(index)?.roomId?.let { + // Add the non-cached item to the caching results + val pairs = cachingResults.getOrDefault(it, mutableListOf()) + pairs.add(CacheResult(index, fromCache = false)) + cachingResults[it] = pairs + } + buildAndCacheItem(roomSummaries, index) + } } else { + roomSummaries.getOrNull(index)?.roomId?.let { + // Add the non-cached item to the caching results + val pairs = cachingResults.getOrDefault(it, mutableListOf()) + pairs.add(CacheResult(index, fromCache = false)) + cachingResults[it] = pairs + } buildAndCacheItem(roomSummaries, index) } } + + // TODO remove once https://github.com/element-hq/element-x-android/issues/5031 has been confirmed as fixed + val duplicates = cachingResults.filter { (_, operations) -> operations.size > 1 } + if (duplicates.isNotEmpty()) { + Timber.e("Found duplicates in room summaries after an UI update: $duplicates. This could be a race condition/caching issue of some kind") + } + _allRooms.emit(roomListRoomSummaries.toImmutableList()) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt index 66931a1f13..e26cea1c94 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt @@ -33,6 +33,12 @@ class RoomSummaryListProcessor( updates.forEach { update -> applyUpdate(update) } + + // TODO remove once https://github.com/element-hq/element-x-android/issues/5031 has been confirmed as fixed + val duplicates = groupingBy { it.roomId }.eachCount().filter { it.value > 1 } + if (duplicates.isNotEmpty()) { + Timber.e("Found duplicates in room summaries after a list update from the SDK: $duplicates. Updates: $updates") + } } }