From b50969437df63935db744977d7c09bbf57093500 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 30 Apr 2026 09:01:35 +0200 Subject: [PATCH] Ensure clearing the cache delete the CacheStore. --- features/preferences/impl/build.gradle.kts | 2 ++ .../impl/tasks/ClearCacheUseCase.kt | 4 ++++ .../impl/tasks/DefaultClearCacheUseCaseTest.kt | 7 +++++++ .../libraries/cachestore/api/CacheStore.kt | 1 + .../cachestore/impl/DatabaseCacheStore.kt | 8 ++++++-- .../android/libraries/cachestore/CacheData.sq | 3 +++ .../impl/DatabaseCacheStoreTest.kt | 18 ++++++++++++++++++ .../sessionstorage/test/InMemoryCacheStore.kt | 4 ++++ 8 files changed, 45 insertions(+), 2 deletions(-) diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts index ad28c90966..33936760f5 100644 --- a/features/preferences/impl/build.gradle.kts +++ b/features/preferences/impl/build.gradle.kts @@ -51,6 +51,7 @@ dependencies { implementation(projects.appconfig) implementation(projects.libraries.core) implementation(projects.libraries.architecture) + implementation(projects.libraries.cachestore.api) implementation(projects.libraries.matrix.api) implementation(projects.libraries.designsystem) implementation(projects.libraries.featureflag.api) @@ -114,6 +115,7 @@ dependencies { testImplementation(projects.features.logout.test) testImplementation(projects.libraries.indicator.test) testImplementation(projects.libraries.pushproviders.test) + testImplementation(projects.libraries.cachestore.test) testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.services.appnavstate.impl) testImplementation(projects.services.analytics.test) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt index 6c26866e93..141adafe2b 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt @@ -14,6 +14,7 @@ import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.Provider import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.features.preferences.impl.DefaultCacheService +import io.element.android.libraries.cachestore.api.CacheStore import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.annotations.ApplicationContext @@ -37,8 +38,11 @@ class DefaultClearCacheUseCase( private val pushService: PushService, private val seenInvitesStore: SeenInvitesStore, private val activeRoomsHolder: ActiveRoomsHolder, + private val cacheStore: CacheStore, ) : ClearCacheUseCase { override suspend fun invoke() = withContext(coroutineDispatchers.io) { + // Clear cache store + cacheStore.deleteAll() // Active rooms should be disposed of before clearing the cache activeRoomsHolder.clear(matrixClient.sessionId) // Clear Matrix cache diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/tasks/DefaultClearCacheUseCaseTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/tasks/DefaultClearCacheUseCaseTest.kt index 6845ecb3a4..1c1cb83def 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/tasks/DefaultClearCacheUseCaseTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/tasks/DefaultClearCacheUseCaseTest.kt @@ -19,6 +19,8 @@ import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.push.test.FakePushService +import io.element.android.libraries.sessionstorage.test.InMemoryCacheStore +import io.element.android.libraries.sessionstorage.test.aCacheData import io.element.android.services.appnavstate.impl.DefaultActiveRoomsHolder import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value @@ -49,6 +51,9 @@ class DefaultClearCacheUseCaseTest { ) val seenInvitesStore = InMemorySeenInvitesStore(setOf(A_ROOM_ID)) assertThat(seenInvitesStore.seenRoomIds().first()).isNotEmpty() + val cacheStore = InMemoryCacheStore( + initialData = mapOf("key1" to aCacheData()) + ) val sut = DefaultClearCacheUseCase( context = InstrumentationRegistry.getInstrumentation().context, matrixClient = matrixClient, @@ -58,9 +63,11 @@ class DefaultClearCacheUseCaseTest { pushService = pushService, seenInvitesStore = seenInvitesStore, activeRoomsHolder = activeRoomsHolder, + cacheStore = cacheStore, ) defaultCacheService.clearedCacheEventFlow.test { sut.invoke() + assertThat(cacheStore.dataMap).isEmpty() clearCacheLambda.assertions().isCalledOnce() setIgnoreRegistrationErrorLambda.assertions().isCalledOnce() .with(value(matrixClient.sessionId), value(false)) diff --git a/libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheStore.kt b/libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheStore.kt index f16a663ed7..5df446f688 100644 --- a/libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheStore.kt +++ b/libraries/cachestore/api/src/main/kotlin/io/element/android/libraries/cachestore/api/CacheStore.kt @@ -11,4 +11,5 @@ interface CacheStore { suspend fun storeData(key: String, data: CacheData) suspend fun getData(key: String): CacheData? suspend fun deleteData(key: String) + suspend fun deleteAll() } diff --git a/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/DatabaseCacheStore.kt b/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/DatabaseCacheStore.kt index 126387da11..54766803f9 100644 --- a/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/DatabaseCacheStore.kt +++ b/libraries/cachestore/impl/src/main/kotlin/io/element/android/libraries/cachestore/impl/DatabaseCacheStore.kt @@ -27,10 +27,14 @@ class DatabaseCacheStore( override suspend fun storeData(key: String, data: CacheData) { database.cacheDataQueries.insertData( data.toDbModel(key) - ) + ).await() } override suspend fun deleteData(key: String) { - database.cacheDataQueries.deleteData(key) + database.cacheDataQueries.deleteData(key).await() + } + + override suspend fun deleteAll() { + database.cacheDataQueries.deleteAll().await() } } diff --git a/libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq b/libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq index aa8bacf90b..fd350ac7ba 100644 --- a/libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq +++ b/libraries/cachestore/impl/src/main/sqldelight/io/element/android/libraries/cachestore/CacheData.sq @@ -23,3 +23,6 @@ INSERT OR REPLACE INTO CacheData VALUES ?; deleteData: DELETE FROM CacheData WHERE key = ?; + +deleteAll: +DELETE FROM CacheData; diff --git a/libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseCacheStoreTest.kt b/libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseCacheStoreTest.kt index a2216daa06..36d7e05532 100644 --- a/libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseCacheStoreTest.kt +++ b/libraries/cachestore/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseCacheStoreTest.kt @@ -65,4 +65,22 @@ class DatabaseCacheStoreTest { databaseCacheStore.deleteData(A_KEY) assertThat(database.cacheDataQueries.selectData(A_KEY).executeAsOneOrNull()).isNull() } + + @Test + fun `deleteAll deletes all the data`() = runTest { + // Assert that no data is stored for the key + assertThat(database.cacheDataQueries.selectData(A_KEY).executeAsOneOrNull()).isNull() + // Store data + databaseCacheStore.storeData(A_KEY, CacheData(A_DATA_1, 1)) + assertThat(database.cacheDataQueries.selectData(A_KEY).executeAsOneOrNull()).isEqualTo( + DbCacheData( + key = A_KEY, + value_ = A_DATA_1, + updatedAt = 1, + ) + ) + // Delete all data + databaseCacheStore.deleteAll() + assertThat(database.cacheDataQueries.selectData(A_KEY).executeAsOneOrNull()).isNull() + } } diff --git a/libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemoryCacheStore.kt b/libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemoryCacheStore.kt index b0f77062ba..f029c8bcde 100644 --- a/libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemoryCacheStore.kt +++ b/libraries/cachestore/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/InMemoryCacheStore.kt @@ -26,4 +26,8 @@ class InMemoryCacheStore( override suspend fun deleteData(key: String) { dataMap.remove(key) } + + override suspend fun deleteAll() { + dataMap.clear() + } }