When a duplicate room list entry is found, report it and remove it (#6006)

* When a duplicate room list entry is found, report it and remove it

* Fix tests and fixtures

* Simplify how the updates are described in the Sentry reports
This commit is contained in:
Jorge Martin Espinosa 2026-01-14 11:56:45 +01:00 committed by GitHub
parent 6d1ed5967b
commit 3ef5e76e99
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 105 additions and 27 deletions

View file

@ -19,6 +19,7 @@ import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.services.analytics.api.AnalyticsService
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope
@ -31,7 +32,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 java.lang.IllegalStateException
import kotlin.time.Duration.Companion.seconds
@Inject
@ -43,6 +44,7 @@ class RoomListDataSource(
@SessionCoroutineScope
private val sessionCoroutineScope: CoroutineScope,
private val dateTimeObserver: DateTimeObserver,
private val analyticsService: AnalyticsService,
) {
init {
observeNotificationSettings()
@ -139,10 +141,18 @@ class RoomListDataSource(
// 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")
}
analyticsService.trackError(
IllegalStateException(
"Found duplicates in room summaries after a local UI update: $duplicates. " +
"This could be a race condition/caching issue of some kind"
)
)
_allRooms.emit(roomListRoomSummaries.toImmutableList())
// Remove duplicates before emitting the new values
_allRooms.emit(roomListRoomSummaries.distinctBy { it.roomId }.toImmutableList())
} else {
_allRooms.emit(roomListRoomSummaries.toImmutableList())
}
}
private fun buildAndCacheItem(roomSummaries: List<RoomSummary>, index: Int): RoomListRoomSummary? {

View file

@ -91,7 +91,7 @@ internal fun aRoomListRoomSummaryList(): ImmutableList<RoomListRoomSummary> {
timestamp = "14:18",
latestEvent = LatestEvent.Synced("A very very very very long message which suites on two lines"),
avatarData = AvatarData("!id", "R", size = AvatarSize.RoomListItem),
id = "!roomId:domain",
id = "!roomId5:domain",
),
aRoomListRoomSummary(
name = "Room#2",

View file

@ -17,6 +17,7 @@ import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
import io.element.android.libraries.matrix.test.room.aRoomSummary
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
@ -103,5 +104,6 @@ class RoomListDataSourceTest {
notificationSettingsService = notificationSettingsService,
sessionCoroutineScope = backgroundScope,
dateTimeObserver = dateTimeObserver,
analyticsService = FakeAnalyticsService(),
)
}

View file

@ -662,6 +662,7 @@ class RoomListPresenterTest {
notificationSettingsService = client.notificationSettingsService,
sessionCoroutineScope = backgroundScope,
dateTimeObserver = FakeDateTimeObserver(),
analyticsService = FakeAnalyticsService(),
),
searchPresenter = searchPresenter,
sessionPreferencesStore = sessionPreferencesStore,