mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-27 20:09:27 +03:00
Attempt to prevent timeline loops
This doesn't fix existing loops, and I'm not sure if this will lead to missing messages (but probably still better than timeline looping...?). Change-Id: I9c14da58736d61b89d09458168eb2d33e9f21d80
This commit is contained in:
parent
b3599aac23
commit
fe4ec79214
2 changed files with 45 additions and 12 deletions
|
@ -209,12 +209,35 @@ internal fun ChunkEntity.nextDisplayIndex(direction: PaginationDirection): Int {
|
|||
}
|
||||
}
|
||||
|
||||
internal fun ChunkEntity.doesPrevChunksVerifyCondition(linkCondition: (ChunkEntity) -> Boolean): Boolean {
|
||||
var prevChunkToCheck = this.prevChunk
|
||||
val visitedChunks = hashSetOf(identifier())
|
||||
while (prevChunkToCheck != null) {
|
||||
if (visitedChunks.contains(prevChunkToCheck.identifier())) {
|
||||
Timber.e("doesPrevChunksVerifyCondition: infinite loop detected at ${prevChunkToCheck.identifier()} while checking ${identifier()}")
|
||||
return false
|
||||
}
|
||||
if (linkCondition(prevChunkToCheck)) {
|
||||
return true
|
||||
}
|
||||
visitedChunks.add(prevChunkToCheck.identifier())
|
||||
prevChunkToCheck = prevChunkToCheck.prevChunk
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
internal fun ChunkEntity.doesNextChunksVerifyCondition(linkCondition: (ChunkEntity) -> Boolean): Boolean {
|
||||
var nextChunkToCheck = this.nextChunk
|
||||
val visitedChunks = hashSetOf(identifier())
|
||||
while (nextChunkToCheck != null) {
|
||||
if (visitedChunks.contains(nextChunkToCheck.identifier())) {
|
||||
Timber.e("doesNextChunksVerifyCondition: infinite loop detected at ${nextChunkToCheck.identifier()} while checking ${identifier()}")
|
||||
return false
|
||||
}
|
||||
if (linkCondition(nextChunkToCheck)) {
|
||||
return true
|
||||
}
|
||||
visitedChunks.add(nextChunkToCheck.identifier())
|
||||
nextChunkToCheck = nextChunkToCheck.nextChunk
|
||||
}
|
||||
return false
|
||||
|
|
|
@ -26,6 +26,8 @@ import org.matrix.android.sdk.api.session.room.send.SendState
|
|||
import org.matrix.android.sdk.internal.database.helper.addIfNecessary
|
||||
import org.matrix.android.sdk.internal.database.helper.addStateEvent
|
||||
import org.matrix.android.sdk.internal.database.helper.addTimelineEvent
|
||||
import org.matrix.android.sdk.internal.database.helper.doesNextChunksVerifyCondition
|
||||
import org.matrix.android.sdk.internal.database.helper.doesPrevChunksVerifyCondition
|
||||
import org.matrix.android.sdk.internal.database.helper.updateThreadSummaryIfNeeded
|
||||
import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
|
||||
import org.matrix.android.sdk.internal.database.mapper.toEntity
|
||||
|
@ -183,24 +185,32 @@ internal class TokenChunkEventPersistor @Inject constructor(
|
|||
// If it exists, we want to stop here, just link the prevChunk
|
||||
val existingChunk = existingTimelineEvent?.chunk?.firstOrNull()
|
||||
if (existingChunk != null) {
|
||||
val alreadyLinkedNext = currentChunk.doesNextChunksVerifyCondition { it == existingChunk }
|
||||
val alreadyLinkedPrev = currentChunk.doesPrevChunksVerifyCondition { it == existingChunk }
|
||||
if (alreadyLinkedNext || alreadyLinkedPrev) {
|
||||
Timber.w("Avoid double link, shouldn't happen in an ideal world | " +
|
||||
"direction: $direction " +
|
||||
"room: $roomId event: $eventId" +
|
||||
"linkedPrev: $alreadyLinkedPrev linkedNext: $alreadyLinkedNext " +
|
||||
"oldChunk: ${existingChunk.identifier()} newChunk: ${existingChunk.identifier()} " +
|
||||
"oldBackwardCheck: ${currentChunk.nextChunk == existingChunk} " +
|
||||
"oldForwardCheck: ${currentChunk.prevChunk == existingChunk}"
|
||||
)
|
||||
// Stop processing here
|
||||
return@processTimelineEvents
|
||||
}
|
||||
when (direction) {
|
||||
PaginationDirection.BACKWARDS -> {
|
||||
if (currentChunk.nextChunk == existingChunk) {
|
||||
Timber.w("Avoid double link, shouldn't happen in an ideal world")
|
||||
} else {
|
||||
Timber.i("Backwards insert chunk: ${existingChunk.identifier()} -> ${currentChunk.identifier()}")
|
||||
currentChunk.prevChunk = existingChunk
|
||||
existingChunk.nextChunk = currentChunk
|
||||
}
|
||||
}
|
||||
PaginationDirection.FORWARDS -> {
|
||||
if (currentChunk.prevChunk == existingChunk) {
|
||||
Timber.w("Avoid double link, shouldn't happen in an ideal world")
|
||||
} else {
|
||||
Timber.i("Forward insert chunk: ${currentChunk.identifier()} -> ${existingChunk.identifier()}")
|
||||
currentChunk.nextChunk = existingChunk
|
||||
existingChunk.prevChunk = currentChunk
|
||||
}
|
||||
}
|
||||
}
|
||||
// Stop processing here
|
||||
return@processTimelineEvents
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue