From 93ef3edab3155ef5f637178b01bf21c48b185f12 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 6 Nov 2019 18:47:11 +0100 Subject: [PATCH] Remove some use of sync write in realm --- .../matrix/android/api/auth/Authenticator.kt | 2 +- .../internal/auth/DefaultAuthenticator.kt | 18 +++- .../internal/auth/SessionParamsStore.kt | 6 +- .../auth/db/RealmSessionParamsStore.kt | 42 +++----- .../database/query/FilterEntityQueries.kt | 18 ++-- .../android/internal/di/MatrixModule.kt | 2 +- .../session/filter/DefaultFilterRepository.kt | 99 +++++++------------ .../session/filter/DefaultFilterService.kt | 31 +----- .../session/filter/DefaultSaveFilterTask.kt | 32 ++++-- .../session/filter/FilterRepository.kt | 8 +- .../internal/session/sync/SyncTokenStore.kt | 17 ++-- .../riotx/features/login/LoginViewModel.kt | 9 +- 12 files changed, 130 insertions(+), 154 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/Authenticator.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/Authenticator.kt index 77a3cde249..c1dfa465fb 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/Authenticator.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/Authenticator.kt @@ -67,5 +67,5 @@ interface Authenticator { /** * Create a session after a SSO successful login */ - fun createSessionFromSso(credentials: Credentials, homeServerConnectionConfig: HomeServerConnectionConfig): Session + fun createSessionFromSso(credentials: Credentials, homeServerConnectionConfig: HomeServerConnectionConfig, callback: MatrixCallback): Cancelable } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt index e379090677..0192715ae5 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/DefaultAuthenticator.kt @@ -112,10 +112,24 @@ internal class DefaultAuthenticator @Inject constructor(@Unauthenticated sessionManager.getOrCreateSession(sessionParams) } - override fun createSessionFromSso(credentials: Credentials, homeServerConnectionConfig: HomeServerConnectionConfig): Session { + override fun createSessionFromSso(credentials: Credentials, + homeServerConnectionConfig: HomeServerConnectionConfig, + callback: MatrixCallback): Cancelable { + val job = GlobalScope.launch(coroutineDispatchers.main) { + val sessionOrFailure = runCatching { + createSessionFromSso(credentials, homeServerConnectionConfig) + } + sessionOrFailure.foldToCallback(callback) + } + return CancelableCoroutine(job) + + } + + private suspend fun createSessionFromSso(credentials: Credentials, + homeServerConnectionConfig: HomeServerConnectionConfig): Session = withContext(coroutineDispatchers.computation) { val sessionParams = SessionParams(credentials, homeServerConnectionConfig) sessionParamsStore.save(sessionParams) - return sessionManager.getOrCreateSession(sessionParams) + sessionManager.getOrCreateSession(sessionParams) } private fun buildAuthAPI(homeServerConnectionConfig: HomeServerConnectionConfig): AuthAPI { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt index e1fef7e2eb..88beb92111 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt @@ -27,9 +27,9 @@ internal interface SessionParamsStore { fun getAll(): List - fun save(sessionParams: SessionParams): Try + suspend fun save(sessionParams: SessionParams) - fun delete(userId: String): Try + suspend fun delete(userId: String) - fun deleteAll(): Try + suspend fun deleteAll() } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt index 7ec5d24559..00fde2682e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt @@ -16,9 +16,9 @@ package im.vector.matrix.android.internal.auth.db -import arrow.core.Try import im.vector.matrix.android.api.auth.data.SessionParams import im.vector.matrix.android.internal.auth.SessionParamsStore +import im.vector.matrix.android.internal.database.awaitTransaction import im.vector.matrix.android.internal.di.AuthDatabase import io.realm.Realm import io.realm.RealmConfiguration @@ -62,41 +62,29 @@ internal class RealmSessionParamsStore @Inject constructor(private val mapper: S return sessionParams } - override fun save(sessionParams: SessionParams): Try { - return Try { + override suspend fun save(sessionParams: SessionParams) { + awaitTransaction(realmConfiguration) { val entity = mapper.map(sessionParams) if (entity != null) { - val realm = Realm.getInstance(realmConfiguration) - realm.executeTransaction { - it.insert(entity) - } - realm.close() + it.insert(entity) } } } - override fun delete(userId: String): Try { - return Try { - val realm = Realm.getInstance(realmConfiguration) - realm.executeTransaction { - it.where(SessionParamsEntity::class.java) - .equalTo(SessionParamsEntityFields.USER_ID, userId) - .findAll() - .deleteAllFromRealm() - } - realm.close() + override suspend fun delete(userId: String) { + awaitTransaction(realmConfiguration) { + it.where(SessionParamsEntity::class.java) + .equalTo(SessionParamsEntityFields.USER_ID, userId) + .findAll() + .deleteAllFromRealm() } } - override fun deleteAll(): Try { - return Try { - val realm = Realm.getInstance(realmConfiguration) - realm.executeTransaction { - it.where(SessionParamsEntity::class.java) - .findAll() - .deleteAllFromRealm() - } - realm.close() + override suspend fun deleteAll() { + awaitTransaction(realmConfiguration) { + it.where(SessionParamsEntity::class.java) + .findAll() + .deleteAllFromRealm() } } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/FilterEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/FilterEntityQueries.kt index 8fbbb1311e..bcc63dd0ba 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/FilterEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/FilterEntityQueries.kt @@ -16,6 +16,7 @@ package im.vector.matrix.android.internal.database.query +import im.vector.matrix.android.internal.database.awaitTransaction import im.vector.matrix.android.internal.database.model.FilterEntity import im.vector.matrix.android.internal.session.filter.FilterFactory import io.realm.Realm @@ -25,18 +26,17 @@ import io.realm.kotlin.where /** * Get the current filter, create one if it does not exist */ -internal fun FilterEntity.Companion.getFilter(realm: Realm): FilterEntity { +internal suspend fun FilterEntity.Companion.getFilter(realm: Realm): FilterEntity { var filter = realm.where().findFirst() if (filter == null) { - realm.executeTransaction { - realm.createObject().apply { - filterBodyJson = FilterFactory.createDefaultFilterBody().toJSONString() - roomEventFilterJson = FilterFactory.createDefaultRoomFilter().toJSONString() - filterId = "" - } + filter = FilterEntity().apply { + filterBodyJson = FilterFactory.createDefaultFilterBody().toJSONString() + roomEventFilterJson = FilterFactory.createDefaultRoomFilter().toJSONString() + filterId = "" + } + awaitTransaction(realm.configuration) { + it.insert(filter) } - filter = realm.where().findFirst()!! } - return filter } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt index 811950ac15..c17864b82b 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt @@ -36,7 +36,7 @@ internal object MatrixModule { @MatrixScope fun providesMatrixCoroutineDispatchers(): MatrixCoroutineDispatchers { return MatrixCoroutineDispatchers(io = Dispatchers.IO, - computation = Dispatchers.IO, + computation = Dispatchers.Default, main = Dispatchers.Main, crypto = createBackgroundHandler("Crypto_Thread").asCoroutineDispatcher(), sync = Executors.newSingleThreadExecutor().asCoroutineDispatcher() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt index 02e6db189a..d7b742fd2d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterRepository.kt @@ -16,54 +16,46 @@ package im.vector.matrix.android.internal.session.filter +import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.internal.database.model.FilterEntity import im.vector.matrix.android.internal.database.model.FilterEntityFields import im.vector.matrix.android.internal.database.query.getFilter import im.vector.matrix.android.internal.di.SessionDatabase +import im.vector.matrix.android.internal.util.awaitTransaction import io.realm.Realm import io.realm.RealmConfiguration import io.realm.kotlin.where import javax.inject.Inject -internal class DefaultFilterRepository @Inject constructor( - @SessionDatabase private val realmConfiguration: RealmConfiguration -) : FilterRepository { +internal class DefaultFilterRepository @Inject constructor(private val monarchy: Monarchy) : FilterRepository { - override fun storeFilter(filterBody: FilterBody, roomEventFilter: RoomEventFilter): Boolean { - val result: Boolean + override suspend fun storeFilter(filterBody: FilterBody, roomEventFilter: RoomEventFilter): Boolean { + return Realm.getInstance(monarchy.realmConfiguration).use { realm -> + val filter = FilterEntity.getFilter(realm) + val result = if (filter.filterBodyJson != filterBody.toJSONString()) { + // Filter has changed, store it and reset the filter Id + monarchy.awaitTransaction { + // We manage only one filter for now + val filterBodyJson = filterBody.toJSONString() + val roomEventFilterJson = roomEventFilter.toJSONString() - val realm = Realm.getInstance(realmConfiguration) + val filterEntity = FilterEntity.getFilter(it) - val filter = FilterEntity.getFilter(realm) - - if (filter.filterBodyJson != filterBody.toJSONString()) { - // Filter has changed, store it and reset the filter Id - realm.executeTransaction { - // We manage only one filter for now - val filterBodyJson = filterBody.toJSONString() - val roomEventFilterJson = roomEventFilter.toJSONString() - - val filterEntity = FilterEntity.getFilter(it) - - filterEntity.filterBodyJson = filterBodyJson - filterEntity.roomEventFilterJson = roomEventFilterJson - // Reset filterId - filterEntity.filterId = "" + filterEntity.filterBodyJson = filterBodyJson + filterEntity.roomEventFilterJson = roomEventFilterJson + // Reset filterId + filterEntity.filterId = "" + } + true + } else { + filter.filterId.isBlank() } - result = true - } else { - result = filter.filterId.isBlank() + result } - - realm.close() - - return result } - override fun storeFilterId(filterBody: FilterBody, filterId: String) { - val realm = Realm.getInstance(realmConfiguration) - - realm.executeTransaction { + override suspend fun storeFilterId(filterBody: FilterBody, filterId: String) { + monarchy.awaitTransaction { // We manage only one filter for now val filterBodyJson = filterBody.toJSONString() @@ -73,39 +65,24 @@ internal class DefaultFilterRepository @Inject constructor( ?.findFirst() ?.filterId = filterId } - - realm.close() } - override fun getFilter(): String { - val result: String - - val realm = Realm.getInstance(realmConfiguration) - - val filter = FilterEntity.getFilter(realm) - - result = if (filter.filterId.isBlank()) { - // Use the Json format - filter.filterBodyJson - } else { - // Use FilterId - filter.filterId + override suspend fun getFilter(): String { + return Realm.getInstance(monarchy.realmConfiguration).use { + val filter = FilterEntity.getFilter(it) + if (filter.filterId.isBlank()) { + // Use the Json format + filter.filterBodyJson + } else { + // Use FilterId + filter.filterId + } } - - realm.close() - - return result } - override fun getRoomFilter(): String { - val realm = Realm.getInstance(realmConfiguration) - - val filter = FilterEntity.getFilter(realm) - - val result = filter.roomEventFilterJson - - realm.close() - - return result + override suspend fun getRoomFilter(): String { + return Realm.getInstance(monarchy.realmConfiguration).use { + FilterEntity.getFilter(it).roomEventFilterJson + } } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterService.kt index 84e820ebca..c85d949d0a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultFilterService.kt @@ -21,36 +21,13 @@ import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith import javax.inject.Inject -internal class DefaultFilterService @Inject constructor(private val filterRepository: FilterRepository, - private val saveFilterTask: SaveFilterTask, +internal class DefaultFilterService @Inject constructor(private val saveFilterTask: SaveFilterTask, private val taskExecutor: TaskExecutor) : FilterService { // TODO Pass a list of support events instead override fun setFilter(filterPreset: FilterService.FilterPreset) { - val filterBody = when (filterPreset) { - FilterService.FilterPreset.RiotFilter -> { - FilterFactory.createRiotFilterBody() - } - FilterService.FilterPreset.NoFilter -> { - FilterFactory.createDefaultFilterBody() - } - } - - val roomFilter = when (filterPreset) { - FilterService.FilterPreset.RiotFilter -> { - FilterFactory.createRiotRoomFilter() - } - FilterService.FilterPreset.NoFilter -> { - FilterFactory.createDefaultRoomFilter() - } - } - - val updated = filterRepository.storeFilter(filterBody, roomFilter) - - if (updated) { - saveFilterTask - .configureWith(SaveFilterTask.Params(filterBody)) - .executeBy(taskExecutor) - } + saveFilterTask + .configureWith(SaveFilterTask.Params(filterPreset)) + .executeBy(taskExecutor) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt index b98049675e..08985bf17d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/DefaultSaveFilterTask.kt @@ -16,18 +16,19 @@ package im.vector.matrix.android.internal.session.filter +import im.vector.matrix.android.api.session.sync.FilterService import im.vector.matrix.android.internal.di.UserId import im.vector.matrix.android.internal.network.executeRequest import im.vector.matrix.android.internal.task.Task import javax.inject.Inject /** - * Save a filter to the server + * Save a filter, in db and if any changes, upload to the server */ internal interface SaveFilterTask : Task { data class Params( - val filter: FilterBody + val filterPreset: FilterService.FilterPreset ) } @@ -37,10 +38,29 @@ internal class DefaultSaveFilterTask @Inject constructor(@UserId private val use ) : SaveFilterTask { override suspend fun execute(params: SaveFilterTask.Params) { - val filterResponse = executeRequest { - // TODO auto retry - apiCall = filterAPI.uploadFilter(userId, params.filter) + val filterBody = when (params.filterPreset) { + FilterService.FilterPreset.RiotFilter -> { + FilterFactory.createRiotFilterBody() + } + FilterService.FilterPreset.NoFilter -> { + FilterFactory.createDefaultFilterBody() + } + } + val roomFilter = when (params.filterPreset) { + FilterService.FilterPreset.RiotFilter -> { + FilterFactory.createRiotRoomFilter() + } + FilterService.FilterPreset.NoFilter -> { + FilterFactory.createDefaultRoomFilter() + } + } + val updated = filterRepository.storeFilter(filterBody, roomFilter) + if (updated) { + val filterResponse = executeRequest { + // TODO auto retry + apiCall = filterAPI.uploadFilter(userId, filterBody) + } + filterRepository.storeFilterId(filterBody, filterResponse.filterId) } - filterRepository.storeFilterId(params.filter, filterResponse.filterId) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterRepository.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterRepository.kt index 092d9ff766..d205ea8a87 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterRepository.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterRepository.kt @@ -21,20 +21,20 @@ internal interface FilterRepository { /** * Return true if the filterBody has changed, or need to be sent to the server */ - fun storeFilter(filterBody: FilterBody, roomEventFilter: RoomEventFilter): Boolean + suspend fun storeFilter(filterBody: FilterBody, roomEventFilter: RoomEventFilter): Boolean /** * Set the filterId of this filter */ - fun storeFilterId(filterBody: FilterBody, filterId: String) + suspend fun storeFilterId(filterBody: FilterBody, filterId: String) /** * Return filter json or filter id */ - fun getFilter(): String + suspend fun getFilter(): String /** * Return the room filter */ - fun getRoomFilter(): String + suspend fun getRoomFilter(): String } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt index f56ee3352f..3d9052bee6 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncTokenStore.kt @@ -16,27 +16,26 @@ package im.vector.matrix.android.internal.session.sync +import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.internal.database.model.SyncEntity import im.vector.matrix.android.internal.di.SessionDatabase +import im.vector.matrix.android.internal.util.awaitTransaction import io.realm.Realm import io.realm.RealmConfiguration import javax.inject.Inject -internal class SyncTokenStore @Inject constructor(@SessionDatabase private val realmConfiguration: RealmConfiguration) { +internal class SyncTokenStore @Inject constructor(private val monarchy: Monarchy) { fun getLastToken(): String? { - val realm = Realm.getInstance(realmConfiguration) - val token = realm.where(SyncEntity::class.java).findFirst()?.nextBatch - realm.close() - return token + return Realm.getInstance(monarchy.realmConfiguration).use { + it.where(SyncEntity::class.java).findFirst()?.nextBatch + } } - fun saveToken(token: String?) { - val realm = Realm.getInstance(realmConfiguration) - realm.executeTransaction { + suspend fun saveToken(token: String?) { + monarchy.awaitTransaction { val sync = SyncEntity(token) it.insertOrUpdate(sync) } - realm.close() } } diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt index 0a324df6b9..7d9b53a875 100644 --- a/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/login/LoginViewModel.kt @@ -116,7 +116,6 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi private fun onSessionCreated(session: Session) { activeSessionHolder.setActiveSession(session) session.configureAndStart(pushRuleTriggerListener, sessionListener) - setState { copy( asyncLoginAction = Success(Unit) @@ -131,9 +130,11 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi // Should not happen Timber.w("homeServerConnectionConfig is null") } else { - val session = authenticator.createSessionFromSso(action.credentials, homeServerConnectionConfigFinal) - - onSessionCreated(session) + authenticator.createSessionFromSso(action.credentials, homeServerConnectionConfigFinal, object : MatrixCallback { + override fun onSuccess(data: Session) { + onSessionCreated(data) + } + }) } }