Read receipts: use a simpler strategy when it's initialSync

This commit is contained in:
ganfra 2019-08-08 15:03:36 +02:00
parent b4ce8748cb
commit d98567045c
3 changed files with 54 additions and 16 deletions

View File

@ -31,27 +31,62 @@ import javax.inject.Inject
// dict value ts value // dict value ts value
typealias ReadReceiptContent = Map<String, Map<String, Map<String, Map<String, Double>>>> typealias ReadReceiptContent = Map<String, Map<String, Map<String, Map<String, Double>>>>
private const val READ_KEY = "m.read"
private const val TIMESTAMP_KEY = "ts"
internal class ReadReceiptHandler @Inject constructor() { internal class ReadReceiptHandler @Inject constructor() {
fun handle(realm: Realm, roomId: String, content: ReadReceiptContent?) { fun handle(realm: Realm, roomId: String, content: ReadReceiptContent?, isInitialSync: Boolean) {
if (content == null) { if (content == null) {
return return
} }
try { try {
handleReadReceiptContent(realm, roomId, content) handleReadReceiptContent(realm, roomId, content, isInitialSync)
} catch (exception: Exception) { } catch (exception: Exception) {
Timber.e("Fail to handle read receipt for room $roomId") Timber.e("Fail to handle read receipt for room $roomId")
} }
} }
private fun handleReadReceiptContent(realm: Realm, roomId: String, content: ReadReceiptContent) { private fun handleReadReceiptContent(realm: Realm, roomId: String, content: ReadReceiptContent, isInitialSync: Boolean) {
if (isInitialSync) {
initialSyncStrategy(realm, roomId, content)
} else {
incrementalSyncStrategy(realm, roomId, content)
}
}
private fun initialSyncStrategy(realm: Realm, roomId: String, content: ReadReceiptContent) {
val readReceiptSummaries = ArrayList<ReadReceiptsSummaryEntity>()
for ((eventId, receiptDict) in content) { for ((eventId, receiptDict) in content) {
val userIdsDict = receiptDict["m.read"] ?: continue val userIdsDict = receiptDict[READ_KEY] ?: continue
val readReceiptsSummary = ReadReceiptsSummaryEntity(eventId = eventId)
for ((userId, paramsDict) in userIdsDict) {
val ts = paramsDict[TIMESTAMP_KEY] ?: 0.0
val primaryKey = "${roomId}_$userId"
val receiptEntity = ReadReceiptEntity().apply {
this.primaryKey = primaryKey
this.eventId = eventId
this.roomId = roomId
this.userId = userId
this.originServerTs = ts
}
readReceiptsSummary.readReceipts.add(receiptEntity)
}
readReceiptSummaries.add(readReceiptsSummary)
}
realm.insertOrUpdate(readReceiptSummaries)
}
private fun incrementalSyncStrategy(realm: Realm, roomId: String, content: ReadReceiptContent) {
for ((eventId, receiptDict) in content) {
val userIdsDict = receiptDict[READ_KEY] ?: continue
val readReceiptsSummary = ReadReceiptsSummaryEntity.where(realm, eventId).findFirst() val readReceiptsSummary = ReadReceiptsSummaryEntity.where(realm, eventId).findFirst()
?: realm.createObject(ReadReceiptsSummaryEntity::class.java, eventId) ?: realm.createObject(ReadReceiptsSummaryEntity::class.java, eventId)
for ((userId, paramsDict) in userIdsDict) { for ((userId, paramsDict) in userIdsDict) {
val ts = paramsDict["ts"] ?: 0.0 val ts = paramsDict[TIMESTAMP_KEY] ?: 0.0
val primaryKey = "${roomId}_$userId" val primaryKey = "${roomId}_$userId"
val receiptEntity = ReadReceiptEntity.where(realm, roomId, userId).findFirst() val receiptEntity = ReadReceiptEntity.where(realm, roomId, userId).findFirst()
?: realm.createObject(ReadReceiptEntity::class.java, primaryKey) ?: realm.createObject(ReadReceiptEntity::class.java, primaryKey)
@ -69,4 +104,5 @@ internal class ReadReceiptHandler @Inject constructor() {
} }
} }
} }
} }

View File

@ -62,11 +62,11 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
data class LEFT(val data: Map<String, RoomSync>) : HandlingStrategy() data class LEFT(val data: Map<String, RoomSync>) : HandlingStrategy()
} }
fun handle(roomsSyncResponse: RoomsSyncResponse, reporter: DefaultInitialSyncProgressService? = null) { fun handle(roomsSyncResponse: RoomsSyncResponse, isInitialSync: Boolean, reporter: DefaultInitialSyncProgressService? = null) {
monarchy.runTransactionSync { realm -> monarchy.runTransactionSync { realm ->
handleRoomSync(realm, HandlingStrategy.JOINED(roomsSyncResponse.join), reporter) handleRoomSync(realm, HandlingStrategy.JOINED(roomsSyncResponse.join), isInitialSync, reporter)
handleRoomSync(realm, HandlingStrategy.INVITED(roomsSyncResponse.invite), reporter) handleRoomSync(realm, HandlingStrategy.INVITED(roomsSyncResponse.invite), isInitialSync, reporter)
handleRoomSync(realm, HandlingStrategy.LEFT(roomsSyncResponse.leave), reporter) handleRoomSync(realm, HandlingStrategy.LEFT(roomsSyncResponse.leave), isInitialSync, reporter)
} }
//handle event for bing rule checks //handle event for bing rule checks
@ -89,12 +89,12 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
// PRIVATE METHODS ***************************************************************************** // PRIVATE METHODS *****************************************************************************
private fun handleRoomSync(realm: Realm, handlingStrategy: HandlingStrategy, reporter: DefaultInitialSyncProgressService?) { private fun handleRoomSync(realm: Realm, handlingStrategy: HandlingStrategy, isInitialSync: Boolean, reporter: DefaultInitialSyncProgressService?) {
val rooms = when (handlingStrategy) { val rooms = when (handlingStrategy) {
is HandlingStrategy.JOINED -> is HandlingStrategy.JOINED ->
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_joined_rooms, 0.6f) { handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_joined_rooms, 0.6f) {
handleJoinedRoom(realm, it.key, it.value) handleJoinedRoom(realm, it.key, it.value, isInitialSync)
} }
is HandlingStrategy.INVITED -> is HandlingStrategy.INVITED ->
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_invited_rooms, 0.4f) { handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_invited_rooms, 0.4f) {
@ -112,7 +112,8 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
private fun handleJoinedRoom(realm: Realm, private fun handleJoinedRoom(realm: Realm,
roomId: String, roomId: String,
roomSync: RoomSync): RoomEntity { roomSync: RoomSync,
isInitalSync: Boolean): RoomEntity {
Timber.v("Handle join sync for room $roomId") Timber.v("Handle join sync for room $roomId")
@ -152,7 +153,7 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
roomSummaryUpdater.update(realm, roomId, Membership.JOIN, roomSync.summary, roomSync.unreadNotifications) roomSummaryUpdater.update(realm, roomId, Membership.JOIN, roomSync.summary, roomSync.unreadNotifications)
if (roomSync.ephemeral != null && roomSync.ephemeral.events.isNotEmpty()) { if (roomSync.ephemeral != null && roomSync.ephemeral.events.isNotEmpty()) {
handleEphemeral(realm, roomId, roomSync.ephemeral) handleEphemeral(realm, roomId, roomSync.ephemeral, isInitalSync)
} }
if (roomSync.accountData != null && roomSync.accountData.events.isNullOrEmpty().not()) { if (roomSync.accountData != null && roomSync.accountData.events.isNullOrEmpty().not()) {
@ -236,11 +237,12 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
private fun handleEphemeral(realm: Realm, private fun handleEphemeral(realm: Realm,
roomId: String, roomId: String,
ephemeral: RoomSyncEphemeral) { ephemeral: RoomSyncEphemeral,
isInitalSync: Boolean) {
for (event in ephemeral.events) { for (event in ephemeral.events) {
if (event.type != EventType.RECEIPT) continue if (event.type != EventType.RECEIPT) continue
val readReceiptContent = event.content as? ReadReceiptContent ?: continue val readReceiptContent = event.content as? ReadReceiptContent ?: continue
readReceiptHandler.handle(realm, roomId, readReceiptContent) readReceiptHandler.handle(realm, roomId, readReceiptContent, isInitalSync)
} }
} }

View File

@ -66,7 +66,7 @@ internal class SyncResponseHandler @Inject constructor(private val roomSyncHandl
reportSubtask(reporter, R.string.initial_sync_start_importing_account_rooms, 100, 0.7f) { reportSubtask(reporter, R.string.initial_sync_start_importing_account_rooms, 100, 0.7f) {
if (syncResponse.rooms != null) { if (syncResponse.rooms != null) {
roomSyncHandler.handle(syncResponse.rooms, reporter) roomSyncHandler.handle(syncResponse.rooms, isInitialSync, reporter)
} }
} }
}.also { }.also {