State index management should be ok now

This commit is contained in:
ganfra 2018-11-15 12:37:59 +01:00
parent 18af7c83f3
commit 40f981e454
8 changed files with 58 additions and 43 deletions

View File

@ -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 {


View File

@ -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

View File

@ -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? {

View File

@ -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)
}

View File

@ -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)

}



View File

@ -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)
}

View File

@ -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)
}

View File

@ -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