diff --git a/changelog.d/6394.misc b/changelog.d/6394.misc new file mode 100644 index 0000000000..16b4fbf616 --- /dev/null +++ b/changelog.d/6394.misc @@ -0,0 +1 @@ +Let LoadRoomMembersTask insert by chunk to release db. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/DefaultMembershipService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/DefaultMembershipService.kt index 005d7f26db..ef89ca33a7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/DefaultMembershipService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/DefaultMembershipService.kt @@ -58,7 +58,7 @@ internal class DefaultMembershipService @AssistedInject constructor( } override suspend fun loadRoomMembersIfNeeded() { - val params = LoadRoomMembersTask.Params(roomId, Membership.LEAVE) + val params = LoadRoomMembersTask.Params(roomId, excludeMembership = Membership.LEAVE) loadRoomMembersTask.execute(params) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt index ee8a2170bb..7052eb23e2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt @@ -43,6 +43,7 @@ import org.matrix.android.sdk.internal.session.sync.SyncTokenStore import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.util.awaitTransaction import org.matrix.android.sdk.internal.util.time.Clock +import timber.log.Timber import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -105,32 +106,37 @@ internal class DefaultLoadRoomMembersTask @Inject constructor( } private suspend fun insertInDb(response: RoomMembersResponse, roomId: String) { + val chunks = response.roomMemberEvents.chunked(500) + chunks.forEach { roomMemberEvents -> + monarchy.awaitTransaction { realm -> + Timber.v("Insert ${roomMemberEvents.size} member events in room $roomId") + // We ignore all the already known members + val now = clock.epochMillis() + for (roomMemberEvent in roomMemberEvents) { + if (roomMemberEvent.eventId == null || roomMemberEvent.stateKey == null || roomMemberEvent.type == null) { + continue + } + val ageLocalTs = now - (roomMemberEvent.unsignedData?.age ?: 0) + val eventEntity = roomMemberEvent.toEntity(roomId, SendState.SYNCED, ageLocalTs).copyToRealmOrIgnore(realm, EventInsertType.PAGINATION) + CurrentStateEventEntity.getOrCreate( + realm, + roomId, + roomMemberEvent.stateKey, + roomMemberEvent.type + ).apply { + eventId = roomMemberEvent.eventId + root = eventEntity + } + roomMemberEventHandler.handle(realm, roomId, roomMemberEvent, false) + } + } + } monarchy.awaitTransaction { realm -> - // We ignore all the already known members val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId) - val now = clock.epochMillis() - for (roomMemberEvent in response.roomMemberEvents) { - if (roomMemberEvent.eventId == null || roomMemberEvent.stateKey == null || roomMemberEvent.type == null) { - continue - } - val ageLocalTs = now - (roomMemberEvent.unsignedData?.age ?: 0) - val eventEntity = roomMemberEvent.toEntity(roomId, SendState.SYNCED, ageLocalTs).copyToRealmOrIgnore(realm, EventInsertType.PAGINATION) - CurrentStateEventEntity.getOrCreate( - realm, - roomId, - roomMemberEvent.stateKey, - roomMemberEvent.type - ).apply { - eventId = roomMemberEvent.eventId - root = eventEntity - } - roomMemberEventHandler.handle(realm, roomId, roomMemberEvent, false) - } roomEntity.membersLoadStatus = RoomMembersLoadStatusType.LOADED roomSummaryUpdater.update(realm, roomId, updateMembers = true) } - if (cryptoSessionInfoProvider.isRoomEncrypted(roomId)) { deviceListManager.onRoomMembersLoadedFor(roomId) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt index 1e36e9c6da..fd6552525e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt @@ -83,23 +83,21 @@ internal class RoomMemberEventHandler @Inject constructor( userId: String, roomMember: RoomMemberContent ) { - val roomMemberEntity = RoomMemberEntityFactory.create( - roomId, - userId, - roomMember, - // When an update is happening, insertOrUpdate replace existing values with null if they are not provided, - // but we want to preserve presence record value and not replace it with null - getExistingPresenceState(realm, roomId, userId) - ) - realm.insertOrUpdate(roomMemberEntity) - } - - /** - * Get the already existing presence state for a specific user & room in order NOT to be replaced in RoomMemberSummaryEntity - * by NULL value. - */ - private fun getExistingPresenceState(realm: Realm, roomId: String, userId: String): UserPresenceEntity? { - return RoomMemberSummaryEntity.where(realm, roomId, userId).findFirst()?.userPresenceEntity + val existingRoomMemberSummary = RoomMemberSummaryEntity.where(realm, roomId, userId).findFirst() + if (existingRoomMemberSummary != null) { + existingRoomMemberSummary.displayName = roomMember.displayName + existingRoomMemberSummary.avatarUrl = roomMember.avatarUrl + existingRoomMemberSummary.membership = roomMember.membership + } else { + val presenceEntity = UserPresenceEntity.where(realm, userId).findFirst() + val roomMemberEntity = RoomMemberEntityFactory.create( + roomId, + userId, + roomMember, + presenceEntity + ) + realm.insert(roomMemberEntity) + } } private fun saveUserEntityLocallyIfNecessary( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt index 7795a56cbf..d1eb8794bf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt @@ -33,6 +33,7 @@ import kotlinx.coroutines.withContext import okhttp3.internal.closeQuietly import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings @@ -388,7 +389,7 @@ internal class DefaultTimeline( } private suspend fun loadRoomMembersIfNeeded() { - val loadRoomMembersParam = LoadRoomMembersTask.Params(roomId) + val loadRoomMembersParam = LoadRoomMembersTask.Params(roomId, excludeMembership = Membership.LEAVE) try { loadRoomMembersTask.execute(loadRoomMembersParam) } catch (failure: Throwable) {