Skip to content

Commit

Permalink
Merge pull request #5528 from SpiritCroc/chunk-modification-issue
Browse files Browse the repository at this point in the history
Fix missing/swapped/duplicated messages due to wrong TimelineChunk modifications or insertions
  • Loading branch information
bmarty authored May 31, 2022
2 parents 1fe4ece + 7c0cd1d commit 8e709db
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 1 deletion.
1 change: 1 addition & 0 deletions changelog.d/5528.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix cases of missing, swapped, or duplicated messages
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,31 @@ internal class TimelineChunk(
private fun handleDatabaseChangeSet(results: RealmResults<TimelineEventEntity>, changeSet: OrderedCollectionChangeSet) {
val insertions = changeSet.insertionRanges
for (range in insertions) {
// Check if the insertion's displayIndices match our expectations - or skip this insertion.
// Inconsistencies (missing messages) can happen otherwise if we get insertions before having loaded all timeline events of the chunk.
if (builtEvents.isNotEmpty()) {
// Check consistency to item before insertions
if (range.startIndex > 0) {
val firstInsertion = results[range.startIndex]!!
val lastBeforeInsertion = builtEvents[range.startIndex - 1]
if (firstInsertion.displayIndex + 1 != lastBeforeInsertion.displayIndex) {
Timber.i("handleDatabaseChangeSet: skip insertion at ${range.startIndex}/${builtEvents.size}, " +
"displayIndex mismatch at ${range.startIndex}: ${firstInsertion.displayIndex} -> ${lastBeforeInsertion.displayIndex}")
continue
}
}
// Check consistency to item after insertions
if (range.startIndex < builtEvents.size) {
val lastInsertion = results[range.startIndex + range.length - 1]!!
val firstAfterInsertion = builtEvents[range.startIndex]
if (firstAfterInsertion.displayIndex + 1 != lastInsertion.displayIndex) {
Timber.i("handleDatabaseChangeSet: skip insertion at ${range.startIndex}/${builtEvents.size}, " +
"displayIndex mismatch at ${range.startIndex + range.length}: " +
"${firstAfterInsertion.displayIndex} -> ${lastInsertion.displayIndex}")
continue
}
}
}
val newItems = results
.subList(range.startIndex, range.startIndex + range.length)
.map { it.buildAndDecryptIfNeeded() }
Expand All @@ -503,8 +528,12 @@ internal class TimelineChunk(
for (range in modifications) {
for (modificationIndex in (range.startIndex until range.startIndex + range.length)) {
val updatedEntity = results[modificationIndex] ?: continue
val displayIndex = builtEventsIndexes[updatedEntity.eventId]
if (displayIndex == null) {
continue
}
try {
builtEvents[modificationIndex] = updatedEntity.buildAndDecryptIfNeeded()
builtEvents[displayIndex] = updatedEntity.buildAndDecryptIfNeeded()
} catch (failure: Throwable) {
Timber.v("Fail to update items at index: $modificationIndex")
}
Expand Down

0 comments on commit 8e709db

Please sign in to comment.