Fix modifying the wrong events in TimelineChunk

I was observing cases where builtEvents[modificationIndex] was not
having the same eventId as the udpatedEntity in.
In particular, I observed both cases that
- there was no item in the list yet with the same eventId as the updated
  one
- there was an item with the same eventId already in the list, but at a
  different position.

Whenever this happened, the timeline would render missing, duplicated,
or swapped messages in the timeline.

Instead of relying on the modificationIndex to be the same for both the
change set and builtEvents, look up the proper index by eventId.

Change-Id: Ic03bdcc8210ec87b786795848f31e9085096b903
This commit is contained in:
SpiritCroc 2022-03-12 09:32:25 +01:00
parent 8d04a48157
commit 647dd4398e

View file

@ -463,12 +463,13 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity,
for (range in modifications) {
for (modificationIndex in (range.startIndex until range.startIndex + range.length)) {
val updatedEntity = results[modificationIndex] ?: continue
try {
Timber.i("TimelineChunk.handleDatabaseChangeSet: modify ${updatedEntity.eventId} at $modificationIndex (previous: ${builtEvents.getOrNull(modificationIndex)?.eventId})")
if (updatedEntity.eventId != builtEvents.getOrNull(modificationIndex)?.eventId) {
Timber.e("TimelineChunk.handleDatabaseChangeSet: Unexpected modification, bug?!! was using item index $modificationIndex, better could've been ${builtEventsIndexes.getOrDefault(updatedEntity.eventId, null)}")
val displayIndex = builtEventsIndexes.getOrDefault(updatedEntity.eventId, null)
if (displayIndex == null) {
Timber.w("TimelineChunk.handleDatabaseChangeSet: skip modification for ${updatedEntity.eventId} at $modificationIndex, not found in chunk")
continue
}
builtEvents[modificationIndex] = updatedEntity.buildAndDecryptIfNeeded()
try {
builtEvents[displayIndex] = updatedEntity.buildAndDecryptIfNeeded()
} catch (failure: Throwable) {
Timber.v("Fail to update items at index: $modificationIndex")
}