From 3c6eb4bccfadc5bfab31a60bebc2706cbfbd8e70 Mon Sep 17 00:00:00 2001
From: Benoit Marty <benoitm@matrix.org>
Date: Tue, 3 Dec 2019 11:10:11 +0100
Subject: [PATCH] Rework FilterEntityQueries to fix issue of ghost Realm
 reference

---
 .../database/query/FilterEntityQueries.kt     | 29 ++++++++++---------
 .../session/filter/DefaultFilterRepository.kt | 14 +++++----
 2 files changed, 23 insertions(+), 20 deletions(-)

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 4f64f2896f..6902d39a82 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,26 +16,27 @@
 
 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
+import io.realm.kotlin.createObject
 import io.realm.kotlin.where
 
+/**
+ * Get the current filter
+ */
+internal fun FilterEntity.Companion.get(realm: Realm): FilterEntity? {
+    return realm.where<FilterEntity>().findFirst()
+}
+
 /**
  * Get the current filter, create one if it does not exist
  */
-internal suspend fun FilterEntity.Companion.getFilter(realm: Realm): FilterEntity {
-    var filter = realm.where<FilterEntity>().findFirst()
-    if (filter == null) {
-        filter = FilterEntity().apply {
-            filterBodyJson = FilterFactory.createDefaultFilterBody().toJSONString()
-            roomEventFilterJson = FilterFactory.createDefaultRoomFilter().toJSONString()
-            filterId = ""
-        }
-        awaitTransaction(realm.configuration) {
-            it.insert(filter)
-        }
-    }
-    return filter
+internal fun FilterEntity.Companion.getOrCreate(realm: Realm): FilterEntity {
+    return get(realm) ?: realm.createObject<FilterEntity>()
+            .apply {
+                filterBodyJson = FilterFactory.createDefaultFilterBody().toJSONString()
+                roomEventFilterJson = FilterFactory.createDefaultRoomFilter().toJSONString()
+                filterId = ""
+            }
 }
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 33cd245a42..ae8e8ce891 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
@@ -19,7 +19,8 @@ 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.database.query.get
+import im.vector.matrix.android.internal.database.query.getOrCreate
 import im.vector.matrix.android.internal.util.awaitTransaction
 import io.realm.Realm
 import io.realm.kotlin.where
@@ -29,9 +30,10 @@ internal class DefaultFilterRepository @Inject constructor(private val monarchy:
 
     override suspend fun storeFilter(filterBody: FilterBody, roomEventFilter: RoomEventFilter): Boolean {
         return Realm.getInstance(monarchy.realmConfiguration).use { realm ->
-            val filter = FilterEntity.getFilter(realm)
+            val filter = FilterEntity.get(realm)
             // Filter has changed, or no filter Id yet
-            filter.filterBodyJson != filterBody.toJSONString()
+            filter == null
+                    || filter.filterBodyJson != filterBody.toJSONString()
                     || filter.filterId.isBlank()
         }.also { hasChanged ->
             if (hasChanged) {
@@ -42,7 +44,7 @@ internal class DefaultFilterRepository @Inject constructor(private val monarchy:
                     val filterBodyJson = filterBody.toJSONString()
                     val roomEventFilterJson = roomEventFilter.toJSONString()
 
-                    val filterEntity = FilterEntity.getFilter(realm)
+                    val filterEntity = FilterEntity.getOrCreate(realm)
 
                     filterEntity.filterBodyJson = filterBodyJson
                     filterEntity.roomEventFilterJson = roomEventFilterJson
@@ -68,7 +70,7 @@ internal class DefaultFilterRepository @Inject constructor(private val monarchy:
 
     override suspend fun getFilter(): String {
         return Realm.getInstance(monarchy.realmConfiguration).use {
-            val filter = FilterEntity.getFilter(it)
+            val filter = FilterEntity.getOrCreate(it)
             if (filter.filterId.isBlank()) {
                 // Use the Json format
                 filter.filterBodyJson
@@ -81,7 +83,7 @@ internal class DefaultFilterRepository @Inject constructor(private val monarchy:
 
     override suspend fun getRoomFilter(): String {
         return Realm.getInstance(monarchy.realmConfiguration).use {
-            FilterEntity.getFilter(it).roomEventFilterJson
+            FilterEntity.getOrCreate(it).roomEventFilterJson
         }
     }
 }