From 40f981e4544da530c1d33fc8a45b44b20be55afe Mon Sep 17 00:00:00 2001 From: ganfra <francoisg@matrix.org> Date: Thu, 15 Nov 2018 12:37:59 +0100 Subject: [PATCH] State index management should be ok now --- .../matrix/android/api/session/Session.kt | 2 +- .../database/helper/ChunkEntityHelper.kt | 5 --- .../database/query/ChunkEntityQueries.kt | 2 -- .../room/members/LoadRoomMembersRequest.kt | 2 +- .../room/members/RoomMemberExtractor.kt | 35 +++++++++++++------ .../room/timeline/PaginationRequest.kt | 17 +++++---- .../internal/session/sync/RoomSyncHandler.kt | 18 ++++++---- .../session/sync/StateEventsChunkHandler.kt | 20 ++++++----- 8 files changed, 58 insertions(+), 43 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt index 5297cca2a5..cd4af40182 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt @@ -1,9 +1,9 @@ package im.vector.matrix.android.api.session import android.support.annotation.MainThread +import im.vector.matrix.android.api.auth.data.SessionParams import im.vector.matrix.android.api.session.group.GroupService import im.vector.matrix.android.api.session.room.RoomService -import im.vector.matrix.android.api.auth.data.SessionParams interface Session : RoomService, GroupService { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt index 789adbb2fa..554a0f9fa7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt @@ -3,9 +3,7 @@ package im.vector.matrix.android.internal.database.helper import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.internal.database.mapper.asEntity import im.vector.matrix.android.internal.database.model.ChunkEntity -import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.query.fastContains -import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection internal fun ChunkEntity.add(event: Event, stateIndex: Int, paginationDirection: PaginationDirection) { @@ -16,9 +14,6 @@ internal fun ChunkEntity.add(event: Event, stateIndex: Int, paginationDirection: if (event.eventId == null) { return } - if (EventEntity.where(realm, event.eventId).findFirst() != null) { - return - } val eventEntity = event.asEntity() eventEntity.stateIndex = stateIndex diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ChunkEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ChunkEntityQueries.kt index ec21f17871..74b4ab8251 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ChunkEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/ChunkEntityQueries.kt @@ -12,8 +12,6 @@ import io.realm.kotlin.where internal fun ChunkEntity.Companion.where(realm: Realm, roomId: String): RealmQuery<ChunkEntity> { return realm.where<ChunkEntity>() .equalTo("${ChunkEntityFields.ROOM}.${RoomEntityFields.ROOM_ID}", roomId) - .notEqualTo(ChunkEntityFields.PREV_TOKEN, DBConstants.STATE_EVENTS_CHUNK_TOKEN) - .notEqualTo(ChunkEntityFields.NEXT_TOKEN, DBConstants.STATE_EVENTS_CHUNK_TOKEN) } internal fun ChunkEntity.Companion.findWithPrevToken(realm: Realm, roomId: String, prevToken: String?): ChunkEntity? { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersRequest.kt index b24b3bf834..f0b8e5697f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersRequest.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/LoadRoomMembersRequest.kt @@ -58,7 +58,7 @@ internal class LoadRoomMembersRequest(private val roomAPI: RoomAPI, val roomMembers = RoomMembers(realm, roomId).getLoaded() val eventsToInsert = response.roomMemberEvents.filter { !roomMembers.containsKey(it.stateKey) } - val chunk = stateEventsChunkHandler.handle(realm, roomId, eventsToInsert, PaginationDirection.BACKWARDS) + val chunk = stateEventsChunkHandler.handle(realm, roomId, eventsToInsert) if (!roomEntity.chunks.contains(chunk)) { roomEntity.chunks.add(chunk) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/RoomMemberExtractor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/RoomMemberExtractor.kt index be2bb86367..daaf41a4fc 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/RoomMemberExtractor.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/members/RoomMemberExtractor.kt @@ -2,12 +2,14 @@ package im.vector.matrix.android.internal.session.room.members import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.room.model.RoomMember +import im.vector.matrix.android.internal.database.DBConstants import im.vector.matrix.android.internal.database.mapper.asDomain +import im.vector.matrix.android.internal.database.model.ChunkEntity import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.EventEntityFields import im.vector.matrix.android.internal.database.query.findMostSuitableStateEvent +import im.vector.matrix.android.internal.database.query.findWithNextToken import im.vector.matrix.android.internal.database.query.last -import im.vector.matrix.android.internal.database.query.where import io.realm.Realm import io.realm.RealmQuery @@ -16,25 +18,36 @@ internal class RoomMemberExtractor(private val realm: Realm, fun extractFrom(event: EventEntity): RoomMember? { val stateIndex = event.stateIndex + val chunkEntity = event.chunk?.firstOrNull() + ?: throw IllegalStateException("An event should be attached to a chunk") // First of all, try to get the most suitable state event coming from a chunk - return buildQuery(realm, roomId, event.sender) + val roomMember = buildQuery(chunkEntity, event.sender) .findMostSuitableStateEvent(stateIndex = stateIndex) ?.asDomain() - ?.pickContent(stateIndex) + ?.pickContent<RoomMember>(stateIndex) - // If the content is null, we try get the last state event, not coming from a chunk - ?: buildQuery(realm, roomId, event.sender) - .last() - ?.asDomain() - ?.content() + if (roomMember != null) { + return roomMember + } + // If the content is null, we try get the last state event coming from a state events chunk + val stateChunkEntity = ChunkEntity.findWithNextToken(realm, roomId, DBConstants.STATE_EVENTS_CHUNK_TOKEN) + ?: return null + + return buildQuery(stateChunkEntity, event.sender) + .last() + ?.asDomain() + ?.content() } - private fun buildQuery(realm: Realm, roomId: String, sender: String?): RealmQuery<EventEntity> { - return EventEntity - .where(realm, roomId, EventType.STATE_ROOM_MEMBER) + private fun buildQuery(chunk: ChunkEntity, + sender: String?): RealmQuery<EventEntity> { + return chunk.events + .where() + .equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_MEMBER) .equalTo(EventEntityFields.STATE_KEY, sender) + } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt index 2530885bc9..2a71a98496 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt @@ -8,9 +8,12 @@ import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.internal.database.helper.add import im.vector.matrix.android.internal.database.model.ChunkEntity -import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.RoomEntity -import im.vector.matrix.android.internal.database.query.* +import im.vector.matrix.android.internal.database.query.fastContains +import im.vector.matrix.android.internal.database.query.findAllIncludingEvents +import im.vector.matrix.android.internal.database.query.findWithNextToken +import im.vector.matrix.android.internal.database.query.findWithPrevToken +import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.legacy.util.FilterUtil import im.vector.matrix.android.internal.network.executeRequest import im.vector.matrix.android.internal.session.room.RoomAPI @@ -62,10 +65,10 @@ internal class PaginationRequest(private val roomAPI: RoomAPI, return monarchy .tryTransactionSync { realm -> val roomEntity = RoomEntity.where(realm, roomId).findFirst() - ?: throw IllegalStateException("You shouldn't use this method without a room") + ?: throw IllegalStateException("You shouldn't use this method without a room") val currentChunk = ChunkEntity.findWithPrevToken(realm, roomId, receivedChunk.nextToken) - ?: realm.createObject() + ?: realm.createObject() currentChunk.prevToken = receivedChunk.prevToken @@ -79,10 +82,10 @@ internal class PaginationRequest(private val roomAPI: RoomAPI, val incrementStateIndex = direction.incrementStateIndex receivedChunk.events.forEach { event -> - currentChunk.add(event, currentStateIndex, direction) if (EventType.isStateEvent(event.type)) { currentStateIndex += incrementStateIndex } + currentChunk.add(event, currentStateIndex, direction) } if (prevChunk != null) { @@ -110,8 +113,8 @@ internal class PaginationRequest(private val roomAPI: RoomAPI, currentChunk.updateStateIndex(currentStateIndex, direction) - - val stateEventsChunk = stateEventsChunkHandler.handle(realm, roomId, receivedChunk.stateEvents, direction) + // TODO : there is an issue with the pagination sending unwanted room member events + val stateEventsChunk = stateEventsChunkHandler.handle(realm, roomId, receivedChunk.stateEvents) if (!roomEntity.chunks.contains(stateEventsChunk)) { roomEntity.chunks.add(stateEventsChunk) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt index b1bcfa9617..10365ddb52 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt @@ -12,7 +12,11 @@ import im.vector.matrix.android.internal.database.query.findAllIncludingEvents import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection -import im.vector.matrix.android.internal.session.sync.model.* +import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync +import im.vector.matrix.android.internal.session.sync.model.RoomSync +import im.vector.matrix.android.internal.session.sync.model.RoomSyncEphemeral +import im.vector.matrix.android.internal.session.sync.model.RoomSyncSummary +import im.vector.matrix.android.internal.session.sync.model.RoomsSyncResponse import io.realm.Realm import io.realm.kotlin.createObject @@ -39,9 +43,9 @@ internal class RoomSyncHandler(private val monarchy: Monarchy, private fun handleRoomSync(realm: Realm, handlingStrategy: HandlingStrategy) { val rooms = when (handlingStrategy) { - is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedRoom(realm, it.key, it.value) } + is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedRoom(realm, it.key, it.value) } is HandlingStrategy.INVITED -> handlingStrategy.data.map { handleInvitedRoom(realm, it.key, it.value) } - is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftRoom(it.key, it.value) } + is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftRoom(it.key, it.value) } } realm.insertOrUpdate(rooms) } @@ -51,7 +55,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy, roomSync: RoomSync): RoomEntity { val roomEntity = RoomEntity.where(realm, roomId).findFirst() - ?: RoomEntity(roomId) + ?: RoomEntity(roomId) if (roomEntity.membership == MyMembership.INVITED) { roomEntity.chunks.deleteAllFromRealm() @@ -60,7 +64,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy, roomEntity.membership = MyMembership.JOINED if (roomSync.state != null && roomSync.state.events.isNotEmpty()) { - val chunkEntity = stateEventsChunkHandler.handle(realm, roomId, roomSync.state.events, PaginationDirection.FORWARDS) + val chunkEntity = stateEventsChunkHandler.handle(realm, roomId, roomSync.state.events) if (!roomEntity.chunks.contains(chunkEntity)) { roomEntity.chunks.add(chunkEntity) } @@ -113,7 +117,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy, roomSummary: RoomSyncSummary) { val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst() - ?: RoomSummaryEntity(roomId) + ?: RoomSummaryEntity(roomId) if (roomSummary.heroes.isNotEmpty()) { roomSummaryEntity.heroes.clear() @@ -150,7 +154,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy, var currentStateIndex = chunkEntity.nextStateIndex eventList.forEach { event -> if (event.isStateEvent()) { - currentStateIndex += 1 + currentStateIndex += PaginationDirection.FORWARDS.incrementStateIndex } chunkEntity.add(event, currentStateIndex, PaginationDirection.FORWARDS) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/StateEventsChunkHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/StateEventsChunkHandler.kt index d46ecd0a77..785eedf64c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/StateEventsChunkHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/StateEventsChunkHandler.kt @@ -11,19 +11,21 @@ import io.realm.kotlin.createObject internal class StateEventsChunkHandler { - fun handle(realm: Realm, roomId: String, stateEvents: List<Event>, direction: PaginationDirection): ChunkEntity { + fun handle(realm: Realm, roomId: String, stateEvents: List<Event>): ChunkEntity { val chunkEntity = ChunkEntity.findWithNextToken(realm, roomId, DBConstants.STATE_EVENTS_CHUNK_TOKEN) - ?: realm.createObject<ChunkEntity>() - .apply { - prevToken = DBConstants.STATE_EVENTS_CHUNK_TOKEN - nextToken = DBConstants.STATE_EVENTS_CHUNK_TOKEN - nextStateIndex = Int.MIN_VALUE / 2 - prevStateIndex = Int.MIN_VALUE / 2 - } + ?: realm.createObject<ChunkEntity>() + .apply { + prevToken = DBConstants.STATE_EVENTS_CHUNK_TOKEN + nextToken = DBConstants.STATE_EVENTS_CHUNK_TOKEN + nextStateIndex = Int.MIN_VALUE + prevStateIndex = Int.MIN_VALUE + } + // We always consider going forwards as data from server are the most recent + val direction = PaginationDirection.FORWARDS val stateIndex = chunkEntity.stateIndex(direction) + direction.incrementStateIndex stateEvents.forEach { event -> - chunkEntity.add(event, stateIndex, PaginationDirection.FORWARDS) + chunkEntity.add(event, stateIndex, direction) } chunkEntity.updateStateIndex(stateIndex, direction) return chunkEntity