RealmLiveEntity: passes the results and changeSet instead of filtering as it's more efficient

This commit is contained in:
ganfra 2019-07-11 15:30:01 +02:00
parent 1b95336ad3
commit f493ce44f2
5 changed files with 47 additions and 44 deletions

View File

@ -19,6 +19,7 @@ package im.vector.matrix.android.internal.database
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.internal.util.createBackgroundHandler import im.vector.matrix.android.internal.util.createBackgroundHandler
import io.realm.OrderedCollectionChangeSet import io.realm.OrderedCollectionChangeSet
import io.realm.OrderedRealmCollectionChangeListener
import io.realm.Realm import io.realm.Realm
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
import io.realm.RealmObject import io.realm.RealmObject
@ -33,7 +34,7 @@ internal interface LiveEntityObserver {
} }


internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val realmConfiguration: RealmConfiguration) internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val realmConfiguration: RealmConfiguration)
: LiveEntityObserver { : LiveEntityObserver, OrderedRealmCollectionChangeListener<RealmResults<T>> {


private companion object { private companion object {
val BACKGROUND_HANDLER = createBackgroundHandler("LIVE_ENTITY_BACKGROUND") val BACKGROUND_HANDLER = createBackgroundHandler("LIVE_ENTITY_BACKGROUND")
@ -50,9 +51,7 @@ internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val r
val realm = Realm.getInstance(realmConfiguration) val realm = Realm.getInstance(realmConfiguration)
backgroundRealm.set(realm) backgroundRealm.set(realm)
val queryResults = query.createQuery(realm).findAll() val queryResults = query.createQuery(realm).findAll()
queryResults.addChangeListener { t, changeSet -> queryResults.addChangeListener(this)
onChanged(t, changeSet)
}
results = AtomicReference(queryResults) results = AtomicReference(queryResults)
} }
} }
@ -73,19 +72,4 @@ internal abstract class RealmLiveEntityObserver<T : RealmObject>(protected val r
return isStarted.get() return isStarted.get()
} }


private fun onChanged(realmResults: RealmResults<T>, changeSet: OrderedCollectionChangeSet) {
val insertionIndexes = changeSet.insertions
val updateIndexes = changeSet.changes
val deletionIndexes = changeSet.deletions
val inserted = realmResults.filterIndexed { index, _ -> insertionIndexes.contains(index) }
val updated = realmResults.filterIndexed { index, _ -> updateIndexes.contains(index) }
val deleted = realmResults.filterIndexed { index, _ -> deletionIndexes.contains(index) }
processChanges(inserted, updated, deleted)
}

/**
* Do quick treatment or delegate on a task
*/
protected abstract fun processChanges(inserted: List<T>, updated: List<T>, deleted: List<T>)

} }

View File

@ -22,13 +22,20 @@ import androidx.work.WorkManager
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.auth.data.Credentials
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
import im.vector.matrix.android.internal.database.mapper.asDomain
import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.database.model.GroupEntity import im.vector.matrix.android.internal.database.model.GroupEntity
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.session.room.prune.PruneEventTask
import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.worker.WorkManagerUtil import im.vector.matrix.android.internal.worker.WorkManagerUtil
import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder
import im.vector.matrix.android.internal.worker.WorkerParamsFactory import im.vector.matrix.android.internal.worker.WorkerParamsFactory
import io.realm.OrderedCollectionChangeSet
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
import io.realm.RealmResults
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject


private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER" private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER"
@ -40,8 +47,12 @@ internal class GroupSummaryUpdater @Inject constructor(private val context: Cont


override val query = Monarchy.Query<GroupEntity> { GroupEntity.where(it) } override val query = Monarchy.Query<GroupEntity> { GroupEntity.where(it) }


override fun processChanges(inserted: List<GroupEntity>, updated: List<GroupEntity>, deleted: List<GroupEntity>) { override fun onChange(results: RealmResults<GroupEntity>, changeSet: OrderedCollectionChangeSet) {
val newGroupIds = inserted.map { it.groupId } val newGroupIds = changeSet.insertions
.asSequence()
.mapNotNull { results[it]?.groupId}
.toList()

val getGroupDataWorkerParams = GetGroupDataWorker.Params(credentials.userId, newGroupIds) val getGroupDataWorkerParams = GetGroupDataWorker.Params(credentials.userId, newGroupIds)
val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams) val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams)


@ -55,5 +66,4 @@ internal class GroupSummaryUpdater @Inject constructor(private val context: Cont
.enqueue() .enqueue()
} }



} }

View File

@ -25,7 +25,9 @@ import im.vector.matrix.android.internal.database.query.types
import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.task.configureWith
import io.realm.OrderedCollectionChangeSet
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
import io.realm.RealmResults
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject


@ -50,19 +52,18 @@ internal class EventRelationsAggregationUpdater @Inject constructor(@SessionData
) )
} }


override fun processChanges(inserted: List<EventEntity>, updated: List<EventEntity>, deleted: List<EventEntity>) { override fun onChange(results: RealmResults<EventEntity>, changeSet: OrderedCollectionChangeSet) {
Timber.v("EventRelationsAggregationUpdater called with ${inserted.size} insertions") Timber.v("EventRelationsAggregationUpdater called with ${changeSet.insertions.size} insertions")
val domainInserted = inserted
.map { it.asDomain() }


val insertedDomains = changeSet.insertions
.asSequence()
.mapNotNull { results[it]?.asDomain() }
.toList()
val params = EventRelationsAggregationTask.Params( val params = EventRelationsAggregationTask.Params(
domainInserted, insertedDomains,
credentials.userId credentials.userId
) )

task.configureWith(params).executeBy(taskExecutor)
task.configureWith(params)
.executeBy(taskExecutor)

} }


} }

View File

@ -26,9 +26,12 @@ import im.vector.matrix.android.internal.database.query.types
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.SessionScope
import im.vector.matrix.android.internal.session.room.EventRelationsAggregationTask
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.task.configureWith
import io.realm.OrderedCollectionChangeSet
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
import io.realm.RealmResults
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject


@ -44,18 +47,19 @@ internal class EventsPruner @Inject constructor(@SessionDatabase realmConfigurat


override val query = Monarchy.Query<EventEntity> { EventEntity.types(it, listOf(EventType.REDACTION)) } override val query = Monarchy.Query<EventEntity> { EventEntity.types(it, listOf(EventType.REDACTION)) }


override fun processChanges(inserted: List<EventEntity>, updated: List<EventEntity>, deleted: List<EventEntity>) { override fun onChange(results: RealmResults<EventEntity>, changeSet: OrderedCollectionChangeSet) {
Timber.v("Event pruner called with ${inserted.size} insertions") Timber.v("Event pruner called with ${changeSet.insertions.size} insertions")
val redactionEvents = inserted.map { it.asDomain() }
val insertedDomains = changeSet.insertions
.asSequence()
.mapNotNull { results[it]?.asDomain() }
.toList()


val params = PruneEventTask.Params( val params = PruneEventTask.Params(
redactionEvents, insertedDomains,
credentials.userId credentials.userId
) )

pruneEventTask.configureWith(params).executeBy(taskExecutor)
pruneEventTask.configureWith(params)
.executeBy(taskExecutor)

} }


} }

View File

@ -22,13 +22,13 @@ import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
import im.vector.matrix.android.internal.database.model.EventEntity 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.model.EventEntityFields
import im.vector.matrix.android.internal.database.query.types import im.vector.matrix.android.internal.database.query.types
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.session.SessionScope
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.TaskThread import im.vector.matrix.android.internal.task.TaskThread
import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.task.configureWith
import io.realm.OrderedCollectionChangeSet
import io.realm.RealmConfiguration import io.realm.RealmConfiguration
import io.realm.RealmResults
import io.realm.Sort import io.realm.Sort
import javax.inject.Inject import javax.inject.Inject


@ -42,15 +42,19 @@ internal class UserEntityUpdater @Inject constructor(@SessionDatabase realmConfi
.types(it, listOf(EventType.STATE_ROOM_MEMBER)) .types(it, listOf(EventType.STATE_ROOM_MEMBER))
.sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING) .sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING)
.distinct(EventEntityFields.STATE_KEY) .distinct(EventEntityFields.STATE_KEY)

} }


override fun processChanges(inserted: List<EventEntity>, updated: List<EventEntity>, deleted: List<EventEntity>) { override fun onChange(results: RealmResults<EventEntity>, changeSet: OrderedCollectionChangeSet) {
val roomMembersEvents = inserted.map { it.eventId } val roomMembersEvents = changeSet.insertions
.asSequence()
.mapNotNull { results[it]?.eventId }
.toList()

val taskParams = UpdateUserTask.Params(roomMembersEvents) val taskParams = UpdateUserTask.Params(roomMembersEvents)
updateUserTask updateUserTask
.configureWith(taskParams) .configureWith(taskParams)
.executeOn(TaskThread.IO) .executeOn(TaskThread.IO)
.executeBy(taskExecutor) .executeBy(taskExecutor)
} }

} }