From e9737dff75c070975ff4d860908d301497557fc9 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 3 Jan 2019 17:10:02 +0100 Subject: [PATCH] Add roomId to EventEntity as it makes queries a lot faster and fixes performance issues. --- .../riotredesign/core/extensions/Fragment.kt | 8 +++--- .../features/home/HomeDrawerFragment.kt | 6 ++--- .../main/java/im/vector/matrix/rx/RxRoom.kt | 2 -- .../database/helper/ChunkEntityHelper.kt | 25 ++++++++++--------- .../database/helper/RoomEntityHelper.kt | 8 +++--- .../internal/database/mapper/EventMapper.kt | 14 ++++++++--- .../internal/database/model/EventEntity.kt | 5 ++-- .../database/query/EventEntityQueries.kt | 11 ++------ .../session/room/send/DefaultSendService.kt | 11 +++----- .../room/timeline/TokenChunkEventPersistor.kt | 15 ++++------- .../internal/session/sync/RoomSyncHandler.kt | 16 +++++------- 11 files changed, 52 insertions(+), 69 deletions(-) diff --git a/app/src/main/java/im/vector/riotredesign/core/extensions/Fragment.kt b/app/src/main/java/im/vector/riotredesign/core/extensions/Fragment.kt index 05921312..3d1bb9d2 100644 --- a/app/src/main/java/im/vector/riotredesign/core/extensions/Fragment.kt +++ b/app/src/main/java/im/vector/riotredesign/core/extensions/Fragment.kt @@ -10,6 +10,10 @@ fun Fragment.replaceFragment(fragment: Fragment, frameId: Int) { fragmentManager?.inTransaction { replace(frameId, fragment) } } +fun Fragment.addFragmentToBackstack(fragment: Fragment, frameId: Int, tag: String? = null) { + fragmentManager?.inTransaction { replace(frameId, fragment).addToBackStack(tag) } +} + fun Fragment.addChildFragment(fragment: Fragment, frameId: Int) { childFragmentManager.inTransaction { add(frameId, fragment) } } @@ -18,10 +22,6 @@ fun Fragment.replaceChildFragment(fragment: Fragment, frameId: Int) { childFragmentManager.inTransaction { replace(frameId, fragment) } } -fun Fragment.addFragmentToBackstack(fragment: Fragment, frameId: Int, tag: String? = null) { - fragmentManager?.inTransaction { replace(frameId, fragment).addToBackStack(tag) } -} - fun Fragment.addChildFragmentToBackstack(fragment: Fragment, frameId: Int, tag: String? = null) { childFragmentManager.inTransaction { replace(frameId, fragment).addToBackStack(tag) } } \ No newline at end of file diff --git a/app/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt b/app/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt index 1ef0bcb8..a0ccd361 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/HomeDrawerFragment.kt @@ -5,7 +5,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import im.vector.riotredesign.R -import im.vector.riotredesign.core.extensions.replaceFragment +import im.vector.riotredesign.core.extensions.replaceChildFragment import im.vector.riotredesign.core.platform.RiotFragment import im.vector.riotredesign.features.home.group.GroupListFragment import im.vector.riotredesign.features.home.room.list.RoomListFragment @@ -27,9 +27,9 @@ class HomeDrawerFragment : RiotFragment() { super.onActivityCreated(savedInstanceState) if (savedInstanceState == null) { val groupListFragment = GroupListFragment.newInstance() - replaceFragment(groupListFragment, R.id.groupListFragmentContainer) + replaceChildFragment(groupListFragment, R.id.groupListFragmentContainer) val roomListFragment = RoomListFragment.newInstance() - replaceFragment(roomListFragment, R.id.roomListFragmentContainer) + replaceChildFragment(roomListFragment, R.id.roomListFragmentContainer) } } diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt index a6104cfc..86992356 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt @@ -5,7 +5,6 @@ import im.vector.matrix.android.api.session.events.model.EnrichedEvent import im.vector.matrix.android.api.session.room.Room import im.vector.matrix.android.api.session.room.model.RoomSummary import io.reactivex.Observable -import io.reactivex.schedulers.Schedulers class RxRoom(private val room: Room) { @@ -15,7 +14,6 @@ class RxRoom(private val room: Room) { fun timeline(eventId: String? = null): Observable> { return room.timeline(eventId).asObservable() - .subscribeOn(Schedulers.io()) } } 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 f8d8207a..519e69e1 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 @@ -2,7 +2,8 @@ package im.vector.matrix.android.internal.database.helper import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.EventType -import im.vector.matrix.android.internal.database.mapper.asEntity +import im.vector.matrix.android.internal.database.mapper.toEntity +import im.vector.matrix.android.internal.database.mapper.updateWith 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 @@ -44,13 +45,14 @@ internal fun ChunkEntity.merge(chunkToMerge: ChunkEntity, } } -internal fun ChunkEntity.addAll(events: List, +internal fun ChunkEntity.addAll(roomId: String, + events: List, direction: PaginationDirection, stateIndexOffset: Int = 0, isUnlinked: Boolean = false) { events.forEach { event -> - add(event, direction, stateIndexOffset, isUnlinked) + add(roomId, event, direction, stateIndexOffset, isUnlinked) } } @@ -58,11 +60,13 @@ internal fun ChunkEntity.updateDisplayIndexes() { events.forEachIndexed { index, eventEntity -> eventEntity.displayIndex = index } } -internal fun ChunkEntity.add(event: Event, +internal fun ChunkEntity.add(roomId: String, + event: Event, direction: PaginationDirection, stateIndexOffset: Int = 0, isUnlinked: Boolean = false) { - add(event.asEntity(), direction, stateIndexOffset, isUnlinked) + + add(event.toEntity(roomId), direction, stateIndexOffset, isUnlinked) } internal fun ChunkEntity.add(eventEntity: EventEntity, @@ -76,7 +80,6 @@ internal fun ChunkEntity.add(eventEntity: EventEntity, if (eventEntity.eventId.isEmpty() || events.fastContains(eventEntity.eventId)) { return } - var currentStateIndex = lastStateIndex(direction, defaultValue = stateIndexOffset) if (direction == PaginationDirection.FORWARDS && EventType.isStateEvent(eventEntity.type)) { currentStateIndex += 1 @@ -86,16 +89,14 @@ internal fun ChunkEntity.add(eventEntity: EventEntity, currentStateIndex -= 1 } } - - eventEntity.stateIndex = currentStateIndex - eventEntity.isUnlinked = isUnlinked + eventEntity.updateWith(currentStateIndex, isUnlinked) val position = if (direction == PaginationDirection.FORWARDS) 0 else this.events.size events.add(position, eventEntity) } internal fun ChunkEntity.lastStateIndex(direction: PaginationDirection, defaultValue: Int = 0): Int { return when (direction) { - PaginationDirection.FORWARDS -> events.where().sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING).findFirst()?.stateIndex - PaginationDirection.BACKWARDS -> events.where().sort(EventEntityFields.STATE_INDEX, Sort.ASCENDING).findFirst()?.stateIndex - } ?: defaultValue + PaginationDirection.FORWARDS -> events.where().sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING).findFirst()?.stateIndex + PaginationDirection.BACKWARDS -> events.where().sort(EventEntityFields.STATE_INDEX, Sort.ASCENDING).findFirst()?.stateIndex + } ?: defaultValue } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/RoomEntityHelper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/RoomEntityHelper.kt index 4df958b4..ea4c5a7e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/RoomEntityHelper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/RoomEntityHelper.kt @@ -1,7 +1,8 @@ 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.mapper.toEntity +import im.vector.matrix.android.internal.database.mapper.updateWith import im.vector.matrix.android.internal.database.model.ChunkEntity import im.vector.matrix.android.internal.database.model.RoomEntity @@ -28,9 +29,8 @@ internal fun RoomEntity.addStateEvents(stateEvents: List, if (event.eventId == null) { return@forEach } - val eventEntity = event.asEntity() - eventEntity.stateIndex = stateIndex - eventEntity.isUnlinked = isUnlinked + val eventEntity = event.toEntity(roomId) + eventEntity.updateWith(stateIndex, isUnlinked) untimelinedStateEvents.add(eventEntity) } } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/EventMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/EventMapper.kt index 5d1669b9..d46d0f93 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/EventMapper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/EventMapper.kt @@ -8,9 +8,10 @@ import im.vector.matrix.android.internal.database.model.EventEntity internal object EventMapper { - fun map(event: Event): EventEntity { + fun map(event: Event, roomId: String): EventEntity { val eventEntity = EventEntity() eventEntity.eventId = event.eventId ?: "" + eventEntity.roomId = event.roomId ?: roomId eventEntity.content = ContentMapper.map(event.content) val resolvedPrevContent = event.prevContent ?: event.unsignedData?.prevContent eventEntity.prevContent = ContentMapper.map(resolvedPrevContent) @@ -32,19 +33,24 @@ internal object EventMapper { originServerTs = eventEntity.originServerTs, sender = eventEntity.sender, stateKey = eventEntity.stateKey, - roomId = null, + roomId = eventEntity.roomId, unsignedData = UnsignedData(eventEntity.age), redacts = eventEntity.redacts ) } +} +internal fun EventEntity.updateWith(stateIndex: Int, isUnlinked: Boolean) { + this.stateIndex = stateIndex + this.isUnlinked = isUnlinked } internal fun EventEntity.asDomain(): Event { return EventMapper.map(this) } -internal fun Event.asEntity(): EventEntity { - return EventMapper.map(this) +internal fun Event.toEntity(roomId: String): EventEntity { + return EventMapper.map(this, roomId) } + diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt index 46451ee9..2ac7c0ff 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/EventEntity.kt @@ -8,6 +8,7 @@ import java.util.* internal open class EventEntity(@PrimaryKey var localId: String = UUID.randomUUID().toString(), var eventId: String = "", + var roomId: String = "", var type: String = "", var content: String? = null, var prevContent: String? = null, @@ -27,9 +28,7 @@ internal open class EventEntity(@PrimaryKey var localId: String = UUID.randomUUI BOTH } - companion object { - const val DEFAULT_STATE_INDEX = Int.MIN_VALUE - } + companion object @LinkingObjects("events") val chunk: RealmResults? = null diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt index 7b582287..2d846d8b 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt @@ -1,10 +1,8 @@ package im.vector.matrix.android.internal.database.query -import im.vector.matrix.android.internal.database.model.ChunkEntityFields import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.EventEntity.LinkFilterMode.* import im.vector.matrix.android.internal.database.model.EventEntityFields -import im.vector.matrix.android.internal.database.model.RoomEntityFields import io.realm.Realm import io.realm.RealmList import io.realm.RealmQuery @@ -22,11 +20,7 @@ internal fun EventEntity.Companion.where(realm: Realm, linkFilterMode: EventEntity.LinkFilterMode = LINKED_ONLY): RealmQuery { val query = realm.where() if (roomId != null) { - query.beginGroup() - .equalTo("${EventEntityFields.CHUNK}.${ChunkEntityFields.ROOM}.${RoomEntityFields.ROOM_ID}", roomId) - .or() - .equalTo("${EventEntityFields.ROOM}.${RoomEntityFields.ROOM_ID}", roomId) - .endGroup() + query.equalTo(EventEntityFields.ROOM_ID, roomId) } if (type != null) { query.equalTo(EventEntityFields.TYPE, type) @@ -69,7 +63,6 @@ internal fun RealmList.find(eventId: String): EventEntity? { return this.where().equalTo(EventEntityFields.EVENT_ID, eventId).findFirst() } -internal fun RealmList. - fastContains(eventId: String): Boolean { +internal fun RealmList.fastContains(eventId: String): Boolean { return this.find(eventId) != null } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt index 1623df07..7e96cc27 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt @@ -1,11 +1,6 @@ package im.vector.matrix.android.internal.session.room.send -import androidx.work.BackoffPolicy -import androidx.work.Constraints -import androidx.work.ExistingWorkPolicy -import androidx.work.NetworkType -import androidx.work.OneTimeWorkRequestBuilder -import androidx.work.WorkManager +import androidx.work.* import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.events.model.Event @@ -37,8 +32,8 @@ internal class DefaultSendService(private val roomId: String, monarchy.tryTransactionAsync { realm -> val chunkEntity = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId) - ?: return@tryTransactionAsync - chunkEntity.add(event, PaginationDirection.FORWARDS) + ?: return@tryTransactionAsync + chunkEntity.add(roomId, event, PaginationDirection.FORWARDS) chunkEntity.updateDisplayIndexes() } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt index bf4e9b49..cd2b4868 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt @@ -2,12 +2,7 @@ package im.vector.matrix.android.internal.session.room.timeline import arrow.core.Try import com.zhuinden.monarchy.Monarchy -import im.vector.matrix.android.internal.database.helper.addAll -import im.vector.matrix.android.internal.database.helper.addOrUpdate -import im.vector.matrix.android.internal.database.helper.addStateEvents -import im.vector.matrix.android.internal.database.helper.deleteOnCascade -import im.vector.matrix.android.internal.database.helper.isUnlinked -import im.vector.matrix.android.internal.database.helper.merge +import im.vector.matrix.android.internal.database.helper.* import im.vector.matrix.android.internal.database.model.ChunkEntity import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.query.create @@ -26,7 +21,7 @@ internal class TokenChunkEventPersistor(private val monarchy: Monarchy) { 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 nextToken: String? val prevToken: String? @@ -46,13 +41,13 @@ internal class TokenChunkEventPersistor(private val monarchy: Monarchy) { var currentChunk = if (direction == PaginationDirection.FORWARDS) { prevChunk?.apply { this.nextToken = nextToken } - ?: ChunkEntity.create(realm, prevToken, nextToken) + ?: ChunkEntity.create(realm, prevToken, nextToken) } else { nextChunk?.apply { this.prevToken = prevToken } - ?: ChunkEntity.create(realm, prevToken, nextToken) + ?: ChunkEntity.create(realm, prevToken, nextToken) } - currentChunk.addAll(receivedChunk.events, direction, isUnlinked = currentChunk.isUnlinked()) + currentChunk.addAll(roomId, receivedChunk.events, direction, isUnlinked = currentChunk.isUnlinked()) // Then we merge chunks if needed if (currentChunk != prevChunk && prevChunk != null) { 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 d5305c04..b71160b2 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 @@ -15,11 +15,7 @@ import im.vector.matrix.android.internal.database.model.RoomSummaryEntity 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.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 im.vector.matrix.android.internal.session.sync.model.* import io.realm.Realm import io.realm.kotlin.createObject @@ -45,9 +41,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) } @@ -57,7 +53,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy, roomSync: RoomSync): RoomEntity { val roomEntity = RoomEntity.where(realm, roomId).findFirst() - ?: realm.createObject(roomId) + ?: realm.createObject(roomId) if (roomEntity.membership == MyMembership.INVITED) { roomEntity.chunks.deleteAllFromRealm() @@ -138,7 +134,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy, lastChunk?.isLast = false chunkEntity.isLast = true - chunkEntity.addAll(eventList, PaginationDirection.FORWARDS, stateIndexOffset) + chunkEntity.addAll(roomId, eventList, PaginationDirection.FORWARDS, stateIndexOffset) return chunkEntity } @@ -147,7 +143,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()