From 98890f5365f52eb5604cd2ade0419211a399f9c5 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 16 Jan 2026 16:03:49 +0100 Subject: [PATCH] Create `AppMigration09` to remove the cached `well-known` config from the SDK (#6026) This value was most likely was incorrectly cached due to a previous issue in the SDK --- .../impl/migrations/AppMigration09.kt | 38 +++++++++++++++ .../impl/migrations/AppMigration09Test.kt | 46 +++++++++++++++++++ .../libraries/matrix/api/MatrixClient.kt | 8 ++++ .../libraries/matrix/impl/RustMatrixClient.kt | 7 +++ .../libraries/matrix/test/FakeMatrixClient.kt | 5 ++ 5 files changed, 104 insertions(+) create mode 100644 features/migration/impl/src/main/kotlin/io/element/android/features/migration/impl/migrations/AppMigration09.kt create mode 100644 features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration09Test.kt diff --git a/features/migration/impl/src/main/kotlin/io/element/android/features/migration/impl/migrations/AppMigration09.kt b/features/migration/impl/src/main/kotlin/io/element/android/features/migration/impl/migrations/AppMigration09.kt new file mode 100644 index 0000000000..a420ac8e8f --- /dev/null +++ b/features/migration/impl/src/main/kotlin/io/element/android/features/migration/impl/migrations/AppMigration09.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.migration.impl.migrations + +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesIntoSet +import dev.zacsweers.metro.Inject +import io.element.android.libraries.matrix.api.MatrixClientProvider +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.sessionstorage.api.SessionStore + +/** + * Ensure we clear the well-known cached config, since it could be invalid due to an SDK issue. + */ +@ContributesIntoSet(AppScope::class) +@Inject +class AppMigration09( + private val sessionStore: SessionStore, + private val matrixClientProvider: MatrixClientProvider, +) : AppMigration { + override val order: Int = 9 + + override suspend fun migrate(isFreshInstall: Boolean) { + if (isFreshInstall) return + + val sessions = sessionStore.getAllSessions() + + for (session in sessions) { + val client = matrixClientProvider.getOrRestore(SessionId(session.userId)).getOrNull() ?: continue + client.resetWellKnownConfig() + } + } +} diff --git a/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration09Test.kt b/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration09Test.kt new file mode 100644 index 0000000000..380ea97464 --- /dev/null +++ b/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration09Test.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.migration.impl.migrations + +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.FakeMatrixClientProvider +import io.element.android.libraries.sessionstorage.test.InMemorySessionStore +import io.element.android.libraries.sessionstorage.test.aSessionData +import io.element.android.tests.testutils.lambda.lambdaRecorder +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class AppMigration09Test { + @Test + fun `migration on fresh install does nothing`() = runTest { + val sessionStore = InMemorySessionStore(initialList = listOf(aSessionData())) + val getClientLambda = lambdaRecorder> { Result.success(FakeMatrixClient()) } + val clientProvider = FakeMatrixClientProvider(getClient = getClientLambda) + val migration = AppMigration09(sessionStore, clientProvider) + migration.migrate(isFreshInstall = true) + + getClientLambda.assertions().isNeverCalled() + } + + @Test + fun `migration on upgrade should invoke the resetWellKnownConfig method`() = runTest { + val sessionStore = InMemorySessionStore(initialList = listOf(aSessionData())) + val resetWellKnownLambda = lambdaRecorder> { Result.success(Unit) } + val getClientLambda = lambdaRecorder> { + Result.success(FakeMatrixClient(resetWellKnownConfigLambda = resetWellKnownLambda)) + } + val clientProvider = FakeMatrixClientProvider(getClient = getClientLambda) + val migration = AppMigration09(sessionStore, clientProvider) + migration.migrate(isFreshInstall = false) + + getClientLambda.assertions().isCalledOnce() + resetWellKnownLambda.assertions().isCalledOnce() + } +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index dca269453a..773dbaaa07 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -214,7 +214,15 @@ interface MatrixClient { */ fun createLinkDesktopHandler(): Result + /** + * Performs a database optimization that should flush cached data and improve performance. + */ suspend fun performDatabaseVacuum(): Result + + /** + * Resets the cached client `well-known` config by the SDK. + */ + suspend fun resetWellKnownConfig(): Result } /** diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index f17f92517a..b24f4b90d8 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -791,6 +791,13 @@ class RustMatrixClient( } } + override suspend fun resetWellKnownConfig(): Result { + return runCatchingExceptions { + Timber.d("Resetting well-known config for session $sessionId") + innerClient.resetWellKnown() + } + } + private suspend fun getCacheSize( includeCryptoDb: Boolean = false, ): Long = withContext(sessionDispatcher) { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index a740e71b0c..56527574d7 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -112,6 +112,7 @@ class FakeMatrixClient( private val markRoomAsFullyReadResult: (RoomId, EventId) -> Result = { _, _ -> lambdaError() }, private val performDatabaseVacuumLambda: () -> Result = { lambdaError() }, private val getDatabaseSizesLambda: () -> Result = { lambdaError() }, + private val resetWellKnownConfigLambda: () -> Result = { lambdaError() }, ) : MatrixClient { var setDisplayNameCalled: Boolean = false private set @@ -379,4 +380,8 @@ class FakeMatrixClient( override fun createLinkMobileHandler(): Result { return createLinkMobileHandlerResult() } + + override suspend fun resetWellKnownConfig(): Result { + return resetWellKnownConfigLambda() + } }