-
Notifications
You must be signed in to change notification settings - Fork 756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Timeline: fix validation of timeline event changes #6462
Conversation
val lastInsertion = results[range.startIndex + range.length - 1] ?: return false | ||
if (firstBuiltEvent.displayIndex + 1 != lastInsertion.displayIndex) { | ||
Timber.v("There is no continuation in the chunk, chunk is not fully loaded yet, skip insert.") | ||
return false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
out of interest, what happens to these events, are they skipped forever?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, they will be loaded when paginating manually!
@@ -558,6 +528,21 @@ internal class TimelineChunk( | |||
} | |||
} | |||
|
|||
private fun validateInsertion(range: OrderedCollectionChangeSet.Range, results: RealmResults<TimelineEventEntity>): Boolean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯 for pulling out a function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can confirm that this fixes the crash from #6461, but I have another crash when closing the thread and going back to the main timeline.
Thread: DefaultTimeline_Thread, Exception: java.lang.IllegalStateException: Cannot create asynchronous query while in a write transaction in /tmp/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_OsResults.cpp line 243
at io.realm.internal.OsResults.nativeStartListening(Native Method)
at io.realm.internal.OsResults.addListener(OsResults.java:673)
at io.realm.RealmResults.addChangeListener(RealmResults.java:734)
at org.matrix.android.sdk.internal.session.room.timeline.TimelineChunk.(TimelineChunk.kt:117)
at org.matrix.android.sdk.internal.session.room.timeline.TimelineChunk.createTimelineChunk(TimelineChunk.kt:567)
at org.matrix.android.sdk.internal.session.room.timeline.TimelineChunk.chunkObjectListener$lambda-2(TimelineChunk.kt:96)
at org.matrix.android.sdk.internal.session.room.timeline.TimelineChunk.$r8$lambda$pCFJ5imq9fIZIR0Q2XoxgvbuKjU(Unknown Source:0)
at org.matrix.android.sdk.internal.session.room.timeline.TimelineChunk$$ExternalSyntheticLambda1.onChange(Unknown Source:4)
See https://github.com/matrix-org/element-android-rageshakes/issues/40144
} | ||
} | ||
} | ||
if (!validateInsertion(range, results)) continue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for extracting
Kudos, SonarCloud Quality Gate passed! |
Yes, this is one of the other issues I was talking about. But it happens randomly and already exists before my fix. |
val firstBuiltEvent = builtEvents.firstOrNull() | ||
if (firstBuiltEvent != null) { | ||
val lastInsertion = results[range.startIndex + range.length - 1] ?: return false | ||
if (firstBuiltEvent.displayIndex + 1 != lastInsertion.displayIndex) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for my understanding, is the only false case when the firstBuiltEvent
exists and it doesn't have the same display index as the results[range.startIndex + range.length - 1]
it might be a little easier to read as a when rather than nested ifs
private fun validateInsertion(range: OrderedCollectionChangeSet.Range, results: RealmResults<TimelineEventEntity>): Boolean {
// Insertion can only happen from LastForward chunk after a sync.
val firstForwardEvent = isLastForward.get().takeIf { it }?.let { builtEvents.firstOrNull() }
return when {
firstForwardEvent == null -> true
firstForwardEvent.nextDisplayIndexDoesNotMatch(results.last(range)) -> {
Timber.v("There is no continuation in the chunk, chunk is not fully loaded yet, skip insert.")
false
}
else -> true
}
}
private fun RealmResults<TimelineEventEntity>.last(range: OrderedCollectionChangeSet.Range): TimelineEventEntity? {
return this[range.startIndex + range.length - 1]
}
private fun TimelineEvent.nextDisplayIndexDoesNotMatch(event: TimelineEventEntity?): Boolean {
return (displayIndex + 1) != event?.displayIndex
}
not a blocker ^^^
Fix #6461