Skip to content
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

Feature/fga/timeline chunks rework #4405

Merged
merged 39 commits into from
Jan 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
9238037
Timeline: try new strategy for handling chunks (no merging)
Sep 7, 2021
4f145e3
Timeline: small on fixes on new implementation
Sep 8, 2021
57e5eca
Merge branch 'develop' into feature/fga/timeline_chunks_rework
Sep 8, 2021
94a6950
Timeline rework: continue branching things.
Sep 8, 2021
da75642
Timeline: add some logs and fix epoxy cache
Sep 17, 2021
2283030
Timeline rework: handle lastForwardChunk
Sep 17, 2021
7f9c191
Timeline rework: add db migration
Sep 17, 2021
63aa5b4
Merge branch 'develop' into feature/fga/timeline_chunks_rework
Sep 17, 2021
b370f84
Timeline rework: add some comments and fix pagination when having ove…
Sep 20, 2021
cd1da73
Timeline rework: make sure migration doesn't crash
Sep 20, 2021
e4896ca
Merge branch 'develop' into feature/fga/timeline_chunks_rework
Nov 2, 2021
d42a2e6
Timeline: don't remove annotations and read receipts when deleting ti…
Nov 3, 2021
ce5ccd4
Timeline: remove useless methods
Nov 3, 2021
52d0da7
Timeline: remove previous lastForward chunk
Nov 3, 2021
a1fdd31
Timeline: just some renaming + constant
Nov 3, 2021
92a37f1
Timeline: fix hasReachedEnd
Nov 4, 2021
52df50a
Timeline: continue trying to make Read marker/receipts working
Nov 10, 2021
8c0b2a6
Timeline: fix double link issue when server is messed up...
Nov 16, 2021
3d27e21
Merge branch 'develop' into feature/fga/timeline_chunks_rework
Nov 16, 2021
e562d76
Timeline: re-add usage of TimelineSettings
Nov 18, 2021
3d31ba9
Merge branch 'develop' into feature/fga/timeline_chunks_rework
Nov 30, 2021
03961fe
Timeline: update when loading states changed
Dec 2, 2021
76eddef
Timeline: avoid notifying when decryption error is same as previous
Dec 2, 2021
014da84
Timeline: try to optimise a bit the loading
Dec 3, 2021
7fa4bf1
Timeline: get off main thread when waiting for positionOrReadMarker
Dec 3, 2021
8ca60ea
Merge branch 'develop' into feature/fga/timeline_chunks_rework
Dec 3, 2021
3217277
Timeline: check for create event to hide loader
Dec 3, 2021
49eee0d
Merge branch 'develop' into feature/fga/timeline_chunks_rework
Dec 3, 2021
29a4fd1
Timeline: make 3 integration tests passing (also add some suspend met…
Dec 7, 2021
bf1be4f
Merge branch 'develop' into feature/fga/timeline_chunks_rework
Dec 8, 2021
b53433e
Timeline: some clean up
Dec 8, 2021
1e2e9e1
Timeline: change a bit when postPagination is triggered
Dec 9, 2021
c830d49
Timeline: remove onStateUpdated in controller
Dec 9, 2021
31ba912
Timeline: url preview listen to Flow in ViewModel
Dec 9, 2021
faebf95
Timeline: remove LifecycleOwner on EpoxyModel as it's not used (and t…
Dec 9, 2021
bf287d1
Timeline: clean up
Dec 9, 2021
1280687
Merge branch 'develop' into feature/fga/timeline_chunks_rework
Dec 9, 2021
12b775c
Timeline : clean after PR reviews
Jan 3, 2022
9121585
Merge branch 'develop' into feature/fga/timeline_chunks_rework
Jan 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/4405.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Change internal timeline management.
1 change: 1 addition & 0 deletions changelog.d/4405.removal
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Introduce method onStateUpdated on Timeline.Callback
Original file line number Diff line number Diff line change
Expand Up @@ -145,55 +145,55 @@ class CommonTestHelper(context: Context) {
* @param nbOfMessages the number of time the message will be sent
*/
fun sendTextMessage(room: Room, message: String, nbOfMessages: Int, timeout: Long = TestConstants.timeOutMillis): List<TimelineEvent> {
val sentEvents = ArrayList<TimelineEvent>(nbOfMessages)
val timeline = room.createTimeline(null, TimelineSettings(10))
timeline.start()
waitWithLatch(timeout + 1_000L * nbOfMessages) { latch ->
val timelineListener = object : Timeline.Listener {
override fun onTimelineFailure(throwable: Throwable) {
}

override fun onNewTimelineEvents(eventIds: List<String>) {
// noop
}

override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
val newMessages = snapshot
.filter { it.root.sendState == SendState.SYNCED }
.filter { it.root.getClearType() == EventType.MESSAGE }
.filter { it.root.getClearContent().toModel<MessageContent>()?.body?.startsWith(message) == true }

Timber.v("New synced message size: ${newMessages.size}")
if (newMessages.size == nbOfMessages) {
sentEvents.addAll(newMessages)
// Remove listener now, if not at the next update sendEvents could change
timeline.removeListener(this)
latch.countDown()
}
}
}
timeline.addListener(timelineListener)
sendTextMessagesBatched(room, message, nbOfMessages)
}
val sentEvents = sendTextMessagesBatched(timeline, room, message, nbOfMessages, timeout)
timeline.dispose()
// Check that all events has been created
assertEquals("Message number do not match $sentEvents", nbOfMessages.toLong(), sentEvents.size.toLong())
return sentEvents
}

/**
* Will send nb of messages provided by count parameter but waits a bit every 10 messages to avoid gap in sync
* Will send nb of messages provided by count parameter but waits every 10 messages to avoid gap in sync
*/
private fun sendTextMessagesBatched(room: Room, message: String, count: Int) {
private fun sendTextMessagesBatched(timeline: Timeline, room: Room, message: String, count: Int, timeout: Long): List<TimelineEvent> {
val sentEvents = ArrayList<TimelineEvent>(count)
(1 until count + 1)
.map { "$message #$it" }
.chunked(10)
.forEach { batchedMessages ->
batchedMessages.forEach { formattedMessage ->
room.sendTextMessage(formattedMessage)
}
Thread.sleep(1_000L)
waitWithLatch(timeout) { latch ->
val timelineListener = object : Timeline.Listener {

override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
val allSentMessages = snapshot
.filter { it.root.sendState == SendState.SYNCED }
.filter { it.root.getClearType() == EventType.MESSAGE }
.filter { it.root.getClearContent().toModel<MessageContent>()?.body?.startsWith(message) == true }

val hasSyncedAllBatchedMessages = allSentMessages
.map {
it.root.getClearContent().toModel<MessageContent>()?.body
}
.containsAll(batchedMessages)

if (allSentMessages.size == count) {
sentEvents.addAll(allSentMessages)
}
if (hasSyncedAllBatchedMessages) {
timeline.removeListener(this)
latch.countDown()
}
}
}
timeline.addListener(timelineListener)
}
}
return sentEvents
}

// PRIVATE METHODS *****************************************************************************
Expand Down Expand Up @@ -332,13 +332,6 @@ class CommonTestHelper(context: Context) {

fun createEventListener(latch: CountDownLatch, predicate: (List<TimelineEvent>) -> Boolean): Timeline.Listener {
return object : Timeline.Listener {
override fun onTimelineFailure(throwable: Throwable) {
// noop
}

override fun onNewTimelineEvents(eventIds: List<String>) {
// noop
}

override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
if (predicate(snapshot)) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package org.matrix.android.sdk.session.room.timeline

import kotlinx.coroutines.runBlocking
import org.amshove.kluent.internal.assertEquals
import org.amshove.kluent.shouldBeFalse
import org.amshove.kluent.shouldBeTrue
import org.junit.FixMethodOrder
Expand Down Expand Up @@ -123,54 +125,29 @@ class TimelineForwardPaginationTest : InstrumentedTest {
// Alice paginates BACKWARD and FORWARD of 50 events each
// Then she can only navigate FORWARD
run {
val lock = CountDownLatch(1)
val aliceEventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Alice timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root.content}")
}

// Alice can see the first event of the room (so Back pagination has worked)
snapshot.lastOrNull()?.root?.getClearType() == EventType.STATE_ROOM_CREATE &&
// 6 for room creation item (backward pagination), 1 for the context, and 50 for the forward pagination
snapshot.size == 57 // 6 + 1 + 50
val snapshot = runBlocking {
aliceTimeline.awaitPaginate(Timeline.Direction.BACKWARDS, 50)
aliceTimeline.awaitPaginate(Timeline.Direction.FORWARDS, 50)
}

aliceTimeline.addListener(aliceEventsListener)

// Restart the timeline to the first sent event
// We ask to load event backward and forward
aliceTimeline.paginate(Timeline.Direction.BACKWARDS, 50)
aliceTimeline.paginate(Timeline.Direction.FORWARDS, 50)

commonTestHelper.await(lock)
aliceTimeline.removeAllListeners()

aliceTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeTrue()
aliceTimeline.hasMoreToLoad(Timeline.Direction.BACKWARDS).shouldBeFalse()

assertEquals(EventType.STATE_ROOM_CREATE, snapshot.lastOrNull()?.root?.getClearType())
// 6 for room creation item (backward pagination), 1 for the context, and 50 for the forward pagination
// 6 + 1 + 50
assertEquals(57, snapshot.size)
}

// Alice paginates once again FORWARD for 50 events
// All the timeline is retrieved, she cannot paginate anymore in both direction
run {
val lock = CountDownLatch(1)
val aliceEventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Alice timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root.content}")
}
// 6 for room creation item (backward pagination),and numberOfMessagesToSend (all the message of the room)
snapshot.size == 6 + numberOfMessagesToSend &&
snapshot.checkSendOrder(message, numberOfMessagesToSend, 0)
}

aliceTimeline.addListener(aliceEventsListener)

// Ask for a forward pagination
aliceTimeline.paginate(Timeline.Direction.FORWARDS, 50)

commonTestHelper.await(lock)
aliceTimeline.removeAllListeners()
val snapshot = runBlocking {
aliceTimeline.awaitPaginate(Timeline.Direction.FORWARDS, 50)
}
// 6 for room creation item (backward pagination),and numberOfMessagesToSend (all the message of the room)
snapshot.size == 6 + numberOfMessagesToSend &&
snapshot.checkSendOrder(message, numberOfMessagesToSend, 0)

// The timeline is fully loaded
aliceTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeFalse()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,8 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {

bobTimeline.addListener(eventsListener)

// Restart the timeline to the first sent event, and paginate in both direction
// Restart the timeline to the first sent event
bobTimeline.restartWithEventId(firstMessageFromAliceId)
bobTimeline.paginate(Timeline.Direction.BACKWARDS, 50)
bobTimeline.paginate(Timeline.Direction.FORWARDS, 50)

commonTestHelper.await(lock)
bobTimeline.removeAllListeners()
Expand Down
Loading