BIT-1888 Add the check for the last revision date (#1029)

This commit is contained in:
Oleg Semenenko
2024-02-19 08:34:13 -06:00
committed by Álison Fernandes
parent 2d54fc4616
commit c33fc8cf97
8 changed files with 139 additions and 28 deletions

View File

@@ -77,6 +77,12 @@ interface VaultDiskSource {
*/
suspend fun replaceVaultData(userId: String, vault: SyncResponseJson)
/**
* Trigger re-emissions from the [getCiphers], [getCollections], [getFolders], and [getSends]
* functions.
*/
suspend fun resyncVaultData(userId: String)
/**
* Deletes all stored vault data from the data source for a given [userId].
*/

View File

@@ -16,6 +16,7 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.launch
@@ -264,6 +265,20 @@ class VaultDiskSourceImpl(
}
}
override suspend fun resyncVaultData(userId: String) {
coroutineScope {
val deferredCiphers = async { getCiphers(userId = userId).first() }
val deferredCollections = async { getCollections(userId = userId).first() }
val deferredFolders = async { getFolders(userId = userId).first() }
val deferredSends = async { getSends(userId = userId).first() }
forceCiphersFlow.tryEmit(deferredCiphers.await())
forceCollectionsFlow.tryEmit(deferredCollections.await())
forceFolderFlow.tryEmit(deferredFolders.await())
forceSendFlow.tryEmit(deferredSends.await())
}
}
override suspend fun deleteVaultData(userId: String) {
coroutineScope {
val deferredCiphers = async { ciphersDao.deleteAllCiphers(userId = userId) }

View File

@@ -14,4 +14,7 @@ interface SyncApi {
*/
@GET("sync")
suspend fun sync(): Result<SyncResponseJson>
@GET("/accounts/revision-date")
suspend fun getAccountRevisionDateMillis(): Result<Long>
}

View File

@@ -10,4 +10,10 @@ interface SyncService {
* Make sync request to get vault items.
*/
suspend fun sync(): Result<SyncResponseJson>
/**
* Make a request to get the most recent revision date for the account that is returned as an
* epoch time in milliseconds.
*/
suspend fun getAccountRevisionDateMillis(): Result<Long>
}

View File

@@ -7,4 +7,7 @@ class SyncServiceImpl(
private val syncApi: SyncApi,
) : SyncService {
override suspend fun sync(): Result<SyncResponseJson> = syncApi.sync()
override suspend fun getAccountRevisionDateMillis(): Result<Long> =
syncApi.getAccountRevisionDateMillis()
}

View File

@@ -317,6 +317,27 @@ class VaultRepositoryImpl(
mutableCollectionsStateFlow.updateToPendingOrLoading()
mutableSendDataStateFlow.updateToPendingOrLoading()
syncJob = ioScope.launch {
val lastSyncInstant = settingsDiskSource
.getLastSyncTime(userId = userId)
?.toEpochMilli()
?: 0
syncService
.getAccountRevisionDateMillis()
.fold(
onSuccess = { serverRevisionDate ->
if (serverRevisionDate < lastSyncInstant) {
// We can skip the actual sync call if there is no new data
vaultDiskSource.resyncVaultData(userId)
return@launch
}
},
onFailure = {
updateVaultStateFlowsToError(it)
return@launch
},
)
syncService
.sync()
.fold(
@@ -350,31 +371,7 @@ class VaultRepositoryImpl(
settingsDiskSource.storeLastSyncTime(userId = userId, clock.instant())
},
onFailure = { throwable ->
mutableCiphersStateFlow.update { currentState ->
throwable.toNetworkOrErrorState(
data = currentState.data,
)
}
mutableDomainsStateFlow.update { currentState ->
throwable.toNetworkOrErrorState(
data = currentState.data,
)
}
mutableFoldersStateFlow.update { currentState ->
throwable.toNetworkOrErrorState(
data = currentState.data,
)
}
mutableCollectionsStateFlow.update { currentState ->
throwable.toNetworkOrErrorState(
data = currentState.data,
)
}
mutableSendDataStateFlow.update { currentState ->
throwable.toNetworkOrErrorState(
data = currentState.data,
)
}
updateVaultStateFlowsToError(throwable)
},
)
}
@@ -1407,6 +1404,34 @@ class VaultRepositoryImpl(
}
.onEach { mutableSendDataStateFlow.value = it }
private fun updateVaultStateFlowsToError(throwable: Throwable) {
mutableCiphersStateFlow.update { currentState ->
throwable.toNetworkOrErrorState(
data = currentState.data,
)
}
mutableDomainsStateFlow.update { currentState ->
throwable.toNetworkOrErrorState(
data = currentState.data,
)
}
mutableFoldersStateFlow.update { currentState ->
throwable.toNetworkOrErrorState(
data = currentState.data,
)
}
mutableCollectionsStateFlow.update { currentState ->
throwable.toNetworkOrErrorState(
data = currentState.data,
)
}
mutableSendDataStateFlow.update { currentState ->
throwable.toNetworkOrErrorState(
data = currentState.data,
)
}
}
//region Push notification helpers
/**
* Deletes the cipher specified by [syncCipherDeleteData] from disk.