Skip to content

Commit

Permalink
Tweaked the Synchronizer to fit talk android specifications and updat…
Browse files Browse the repository at this point in the history
…ed OfflineFirstChatRepository to reflect the changes

Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com>
  • Loading branch information
rapterjet2004 committed Jun 12, 2024
1 parent d2cba8b commit bc8f5e3
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ package com.nextcloud.talk.chat.data.network
import com.nextcloud.talk.chat.data.ChatMessageRepository
import com.nextcloud.talk.chat.data.ChatRepository
import com.nextcloud.talk.chat.data.model.ChatMessageModel
import com.nextcloud.talk.data.changeListVersion.ChangeListVersions
import com.nextcloud.talk.data.database.dao.ChatMessagesDao
import com.nextcloud.talk.data.database.mappers.asModel
import com.nextcloud.talk.data.database.model.ChatMessageEntity
Expand All @@ -23,6 +22,7 @@ import javax.inject.Inject
class OfflineFirstChatRepository @Inject constructor(
private val chatDao: ChatMessagesDao,
private val chatRepository: ChatRepository
// TODO implement and inject datastore
) : ChatMessageRepository {
override fun getMessages(id: Long): Flow<List<ChatMessageModel>> =
chatDao.getMessagesForConversation(id).map {
Expand All @@ -34,15 +34,20 @@ class OfflineFirstChatRepository @Inject constructor(

override suspend fun syncWith(synchronizer: Synchronizer): Boolean =
synchronizer.changeListSync(
versionReader = ChangeListVersions::chatVersion,
changeListFetcher = TODO("Need to make implement version checking locally -_- dang it"),
versionUpdater = { latestVersion ->
copy(chatVersion = latestVersion)
versionReader = {
// TODO get the lastReadChatMessageId from the datastore conversationId->lastReadId pairing
return@changeListSync 0L
},
modelFetcher = { lastReadId ->
// TODO pull messages from the server using the last id
return@changeListSync listOf()
},
versionUpdater = { newLastReadId ->
// TODO update the datastore conversationId->lastReadId pairing
},
modelDeleter = chatDao::deleteChatMessages,
modelUpdater = { changedIds ->
// Get from json from network
// chatDao.upsert(json models mapped -> entity)
// TODO chatDao.upsert(json models mapped -> entity)
}
)
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2024 Julius Linus <juliuslinus1@gmail.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package com.nextcloud.talk.data.changeListVersion

/**
* Models any changes from the network, agnostic to what data is being modeled.
* Implemented by Models that support offline synchronization.
*/
interface SyncableModel {

/**
* Model identifier.
*/
var changedId: Long

/**
* Model deletion checker.
*/
var markedForDeletion: Boolean
}
38 changes: 20 additions & 18 deletions app/src/main/java/com/nextcloud/talk/data/sync/SyncUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@
package com.nextcloud.talk.data.sync

import android.util.Log
import com.nextcloud.talk.data.changeListVersion.ChangeListVersions
import com.nextcloud.talk.data.changeListVersion.NetworkChangeList
import com.nextcloud.talk.data.changeListVersion.SyncableModel
import kotlin.coroutines.cancellation.CancellationException

/**
* Interface marker for a class that manages synchronization between local data and a remote
* source for a [Syncable].
*/
interface Synchronizer {
suspend fun getChangeListVersions(): ChangeListVersions

suspend fun updateChangeListVersions(update: ChangeListVersions.() -> ChangeListVersions)
/**
* Updates the version to be synced.
*/
suspend fun updateVersion(update: (Long) -> Unit)

/**
* Syntactic sugar to call [Syncable.syncWith] while omitting the synchronizer argument
Expand Down Expand Up @@ -59,38 +60,39 @@ private suspend fun <T> suspendRunCatching(block: suspend () -> T): Result<T> =

/**
* Utility function for syncing a repository with the network.
* [versionReader] Reads the current version of the model that needs to be synced
* [changeListFetcher] Fetches the change list for the model
* [versionUpdater] Updates the [ChangeListVersions] after a successful sync
* [versionReader] Gets the current version of the model that needs to be synced
* [modelFetcher] Fetches the change list for the model
* [versionUpdater] Updates the version after a successful sync
* [modelDeleter] Deletes models by consuming the ids of the models that have been deleted.
* [modelUpdater] Updates models by consuming the ids of the models that have changed.
*
* Note that the blocks defined above are never run concurrently, and the [Synchronizer]
* implementation must guarantee this.
*/
suspend fun Synchronizer.changeListSync(
versionReader: (ChangeListVersions) -> Int,
changeListFetcher: suspend (Int) -> List<NetworkChangeList>,
versionUpdater: ChangeListVersions.(Int) -> ChangeListVersions,
versionReader: () -> Long,
modelFetcher: suspend (Long) -> List<SyncableModel>,
versionUpdater: (Long) -> Unit,
modelDeleter: suspend (List<Long>) -> Unit,
modelUpdater: suspend (List<Long>) -> Unit
) = suspendRunCatching {
// Fetch the change list since last sync (akin to a git fetch)
val currentVersion = versionReader(getChangeListVersions())
val changeList = changeListFetcher(currentVersion)
val currentVersion = versionReader()
val changeList = modelFetcher(currentVersion)
if (changeList.isEmpty()) return@suspendRunCatching true

val (deleted, updated) = changeList.partition(NetworkChangeList::isDelete)
// Splits the models marked for deletion from the ones that are updated or new
val (deleted, updated) = changeList.partition(SyncableModel::markedForDeletion)

// Delete models that have been deleted server-side
modelDeleter(deleted.map(NetworkChangeList::id))
modelDeleter(deleted.map(SyncableModel::changedId))

// Using the change list, pull down and save the changes (akin to a git pull)
modelUpdater(updated.map(NetworkChangeList::id))
// Using the change list, pull down and upsert the changes (akin to a git pull)
modelUpdater(updated.map(SyncableModel::changedId))

// Update the last synced version (akin to updating local git HEAD)
val latestVersion = changeList.last().changeListVersion
updateChangeListVersions {
val latestVersion = changeList.last().changedId
updateVersion {
versionUpdater(latestVersion)
}
}.isSuccess

0 comments on commit bc8f5e3

Please sign in to comment.