mirror of
https://github.com/element-hq/element-android
synced 2024-11-27 11:59:12 +03:00
Defer the treatment of updating the User profiles to a background Worker.
This commit is contained in:
parent
a7666e2112
commit
94a87744ac
4 changed files with 133 additions and 29 deletions
|
@ -55,6 +55,7 @@ import org.matrix.android.sdk.internal.session.space.SpaceModule
|
|||
import org.matrix.android.sdk.internal.session.sync.SyncModule
|
||||
import org.matrix.android.sdk.internal.session.sync.SyncTask
|
||||
import org.matrix.android.sdk.internal.session.sync.SyncTokenStore
|
||||
import org.matrix.android.sdk.internal.session.sync.handler.UpdateUserWorker
|
||||
import org.matrix.android.sdk.internal.session.sync.job.SyncWorker
|
||||
import org.matrix.android.sdk.internal.session.terms.TermsModule
|
||||
import org.matrix.android.sdk.internal.session.thirdparty.ThirdPartyModule
|
||||
|
@ -128,6 +129,8 @@ internal interface SessionComponent {
|
|||
|
||||
fun inject(worker: UpdateTrustWorker)
|
||||
|
||||
fun inject(worker: UpdateUserWorker)
|
||||
|
||||
fun inject(worker: DeactivateLiveLocationShareWorker)
|
||||
|
||||
@Component.Factory
|
||||
|
|
|
@ -16,30 +16,33 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.session.sync.handler
|
||||
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import androidx.work.BackoffPolicy
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import org.matrix.android.sdk.api.MatrixPatterns
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.user.model.User
|
||||
import org.matrix.android.sdk.internal.crypto.crosssigning.DefaultCrossSigningService
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.session.profile.GetProfileInfoTask
|
||||
import org.matrix.android.sdk.internal.crypto.crosssigning.UpdateTrustWorker
|
||||
import org.matrix.android.sdk.internal.crypto.crosssigning.UpdateTrustWorkerDataRepository
|
||||
import org.matrix.android.sdk.internal.di.SessionId
|
||||
import org.matrix.android.sdk.internal.di.WorkManagerProvider
|
||||
import org.matrix.android.sdk.internal.session.sync.RoomSyncEphemeralTemporaryStore
|
||||
import org.matrix.android.sdk.internal.session.sync.SyncResponsePostTreatmentAggregator
|
||||
import org.matrix.android.sdk.internal.session.sync.model.accountdata.toMutable
|
||||
import org.matrix.android.sdk.internal.session.user.UserEntityFactory
|
||||
import org.matrix.android.sdk.internal.session.user.accountdata.DirectChatsHelper
|
||||
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
|
||||
import org.matrix.android.sdk.internal.util.awaitTransaction
|
||||
import org.matrix.android.sdk.internal.util.logLimit
|
||||
import org.matrix.android.sdk.internal.worker.WorkerParamsFactory
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class SyncResponsePostTreatmentAggregatorHandler @Inject constructor(
|
||||
private val directChatsHelper: DirectChatsHelper,
|
||||
private val ephemeralTemporaryStore: RoomSyncEphemeralTemporaryStore,
|
||||
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
||||
private val getProfileInfoTask: GetProfileInfoTask,
|
||||
private val crossSigningService: DefaultCrossSigningService,
|
||||
@SessionDatabase private val monarchy: Monarchy,
|
||||
private val updateTrustWorkerDataRepository: UpdateTrustWorkerDataRepository,
|
||||
private val workManagerProvider: WorkManagerProvider,
|
||||
@SessionId private val sessionId: String,
|
||||
) {
|
||||
suspend fun handle(aggregator: SyncResponsePostTreatmentAggregator) {
|
||||
cleanupEphemeralFiles(aggregator.ephemeralFilesToDelete)
|
||||
|
@ -83,30 +86,26 @@ internal class SyncResponsePostTreatmentAggregatorHandler @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun fetchAndUpdateUsers(userIdsToFetch: Collection<String>) {
|
||||
fetchUsers(userIdsToFetch)
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?.saveLocally()
|
||||
}
|
||||
private fun fetchAndUpdateUsers(userIdsToFetch: Collection<String>) {
|
||||
if (userIdsToFetch.isEmpty()) return
|
||||
Timber.d("## Configure Worker to update users: ${userIdsToFetch.logLimit()}")
|
||||
val workerParams = UpdateTrustWorker.Params(
|
||||
sessionId = sessionId,
|
||||
filename = updateTrustWorkerDataRepository.createParam(userIdsToFetch.toList())
|
||||
)
|
||||
val workerData = WorkerParamsFactory.toData(workerParams)
|
||||
|
||||
private suspend fun fetchUsers(userIdsToFetch: Collection<String>) = userIdsToFetch.mapNotNull {
|
||||
tryOrNull {
|
||||
val profileJson = getProfileInfoTask.execute(GetProfileInfoTask.Params(it))
|
||||
User.fromJson(it, profileJson)
|
||||
}
|
||||
val workRequest = workManagerProvider.matrixOneTimeWorkRequestBuilder<UpdateUserWorker>()
|
||||
.setInputData(workerData)
|
||||
.setBackoffCriteria(BackoffPolicy.LINEAR, WorkManagerProvider.BACKOFF_DELAY_MILLIS, TimeUnit.MILLISECONDS)
|
||||
.build()
|
||||
|
||||
workManagerProvider.workManager
|
||||
.beginUniqueWork("USER_UPDATE_QUEUE", ExistingWorkPolicy.APPEND_OR_REPLACE, workRequest)
|
||||
.enqueue()
|
||||
}
|
||||
|
||||
private fun handleUserIdsWithDeviceUpdate(userIdsWithDeviceUpdate: Iterable<String>) {
|
||||
crossSigningService.onUsersDeviceUpdate(userIdsWithDeviceUpdate.toList())
|
||||
}
|
||||
|
||||
private suspend fun List<User>.saveLocally() {
|
||||
val userEntities = map { user -> UserEntityFactory.create(user) }
|
||||
Timber.d("## saveLocally()")
|
||||
monarchy.awaitTransaction {
|
||||
Timber.d("## saveLocally() - in transaction")
|
||||
it.insertOrUpdate(userEntities)
|
||||
}
|
||||
Timber.d("## saveLocally() - END")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.session.sync.handler
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.WorkerParameters
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.user.model.User
|
||||
import org.matrix.android.sdk.internal.SessionManager
|
||||
import org.matrix.android.sdk.internal.crypto.crosssigning.UpdateTrustWorker
|
||||
import org.matrix.android.sdk.internal.crypto.crosssigning.UpdateTrustWorkerDataRepository
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.session.SessionComponent
|
||||
import org.matrix.android.sdk.internal.session.profile.GetProfileInfoTask
|
||||
import org.matrix.android.sdk.internal.session.user.UserEntityFactory
|
||||
import org.matrix.android.sdk.internal.util.awaitTransaction
|
||||
import org.matrix.android.sdk.internal.util.logLimit
|
||||
import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Note: We reuse the same type [UpdateTrustWorker.Params], since the inout data are the same.
|
||||
*/
|
||||
internal class UpdateUserWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) :
|
||||
SessionSafeCoroutineWorker<UpdateTrustWorker.Params>(context, params, sessionManager, UpdateTrustWorker.Params::class.java) {
|
||||
|
||||
@SessionDatabase
|
||||
@Inject lateinit var monarchy: Monarchy
|
||||
@Inject lateinit var updateTrustWorkerDataRepository: UpdateTrustWorkerDataRepository
|
||||
@Inject lateinit var getProfileInfoTask: GetProfileInfoTask
|
||||
|
||||
override fun injectWith(injector: SessionComponent) {
|
||||
injector.inject(this)
|
||||
}
|
||||
|
||||
override suspend fun doSafeWork(params: UpdateTrustWorker.Params): Result {
|
||||
val userList = params.filename
|
||||
?.let { updateTrustWorkerDataRepository.getParam(it) }
|
||||
?.userIds
|
||||
?: params.updatedUserIds.orEmpty()
|
||||
|
||||
// List should not be empty, but let's avoid go further in case of empty list
|
||||
if (userList.isNotEmpty()) {
|
||||
Timber.v("## UpdateUserWorker - updating users: ${userList.logLimit()}")
|
||||
fetchAndUpdateUsers(userList)
|
||||
}
|
||||
|
||||
cleanup(params)
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
private suspend fun fetchAndUpdateUsers(userIdsToFetch: Collection<String>) {
|
||||
fetchUsers(userIdsToFetch)
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?.saveLocally()
|
||||
}
|
||||
|
||||
private suspend fun fetchUsers(userIdsToFetch: Collection<String>) = userIdsToFetch.mapNotNull {
|
||||
tryOrNull {
|
||||
val profileJson = getProfileInfoTask.execute(GetProfileInfoTask.Params(it))
|
||||
User.fromJson(it, profileJson)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun List<User>.saveLocally() {
|
||||
val userEntities = map { user -> UserEntityFactory.create(user) }
|
||||
Timber.d("## saveLocally()")
|
||||
monarchy.awaitTransaction {
|
||||
Timber.d("## saveLocally() - in transaction")
|
||||
it.insertOrUpdate(userEntities)
|
||||
}
|
||||
Timber.d("## saveLocally() - END")
|
||||
}
|
||||
|
||||
private fun cleanup(params: UpdateTrustWorker.Params) {
|
||||
params.filename
|
||||
?.let { updateTrustWorkerDataRepository.delete(it) }
|
||||
}
|
||||
|
||||
override fun buildErrorParams(params: UpdateTrustWorker.Params, message: String): UpdateTrustWorker.Params {
|
||||
return params.copy(lastFailureMessage = params.lastFailureMessage ?: message)
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@ import org.matrix.android.sdk.internal.session.room.aggregation.livelocation.Dea
|
|||
import org.matrix.android.sdk.internal.session.room.send.MultipleEventSendingDispatcherWorker
|
||||
import org.matrix.android.sdk.internal.session.room.send.RedactEventWorker
|
||||
import org.matrix.android.sdk.internal.session.room.send.SendEventWorker
|
||||
import org.matrix.android.sdk.internal.session.sync.handler.UpdateUserWorker
|
||||
import org.matrix.android.sdk.internal.session.sync.job.SyncWorker
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
@ -62,6 +63,8 @@ internal class MatrixWorkerFactory @Inject constructor(private val sessionManage
|
|||
SyncWorker(appContext, workerParameters, sessionManager)
|
||||
UpdateTrustWorker::class.java.name ->
|
||||
UpdateTrustWorker(appContext, workerParameters, sessionManager)
|
||||
UpdateUserWorker::class.java.name ->
|
||||
UpdateUserWorker(appContext, workerParameters, sessionManager)
|
||||
UploadContentWorker::class.java.name ->
|
||||
UploadContentWorker(appContext, workerParameters, sessionManager)
|
||||
DeactivateLiveLocationShareWorker::class.java.name ->
|
||||
|
|
Loading…
Reference in a new issue