sync
Synchronizes data and returns a Flow emitting the progress of the sync operation.
Return
A Flow emitting SyncProgress objects representing the progress of the sync operation.
Samples
import dev.atick.core.preferences.data.UserPreferencesDataSource
import dev.atick.core.room.data.LocalDataSource
import dev.atick.core.room.model.SyncAction
import dev.atick.core.utils.suspendRunCatching
import dev.atick.data.model.home.Jetpack
import dev.atick.data.model.home.mapToJetpacks
import dev.atick.data.model.home.toFirebaseJetpack
import dev.atick.data.model.home.toJetpack
import dev.atick.data.model.home.toJetpackEntity
import dev.atick.data.utils.SyncManager
import dev.atick.data.utils.SyncProgress
import dev.atick.firebase.firestore.data.FirebaseDataSource
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import timber.log.Timber
import javax.inject.Inject
fun main() {
//sampleStart
return flow {
val userId = preferencesDataSource.getUserIdOrThrow()
// Unsynced jetpacks
val unsyncedJetpacks = localDataSource.getUnsyncedJetpacks(userId)
val totalUnsyncedJetpacks = unsyncedJetpacks.size
Timber.d("Syncing $totalUnsyncedJetpacks unsynced jetpacks")
// Push updates to remote
unsyncedJetpacks.forEachIndexed { index, unsyncedJetpack ->
when (unsyncedJetpack.syncAction) {
SyncAction.UPSERT -> {
Timber.d("Syncing create/update jetpack: ${unsyncedJetpack.id}")
firebaseDataSource.createOrUpdateJetpack(
unsyncedJetpack
.toFirebaseJetpack()
.copy(
lastSynced = System.currentTimeMillis(),
),
)
}
SyncAction.DELETE -> {
firebaseDataSource.deleteJetpack(
unsyncedJetpack
.toFirebaseJetpack()
.copy(
lastSynced = System.currentTimeMillis(),
),
)
}
SyncAction.NONE -> {
// Do nothing
}
}
localDataSource.markAsSynced(unsyncedJetpack.id)
emit(
SyncProgress(
total = totalUnsyncedJetpacks,
current = index + 1,
message = "Syncing jetpacks with the cloud",
),
)
}
// Remote jetpacks
val lastSynced = localDataSource.getLatestUpdateTimestamp(userId)
val remoteJetpacks = firebaseDataSource.pullJetpacks(userId, lastSynced)
val totalRemoteJetpacks = remoteJetpacks.size
Timber.d("Syncing $totalRemoteJetpacks remote jetpacks")
// Pull updates from remote
// We pull after pushing local changes to save the local changes to the cloud first
// and avoid accidentally overwriting them with stale data
remoteJetpacks.forEachIndexed { index, remoteJetpack ->
localDataSource.upsertJetpack(remoteJetpack.toJetpackEntity())
emit(
SyncProgress(
total = totalRemoteJetpacks,
current = index + 1,
message = "Fetching jetpacks from the cloud",
),
)
}
}
//sampleEnd
}