From 79796c0656a4d03ae4c98ca0af779576a9dc1881 Mon Sep 17 00:00:00 2001 From: Artem Chepurnoy Date: Sun, 18 Aug 2024 17:49:27 +0300 Subject: [PATCH] fix: Do not crash if the key value database is not available #538 --- .../src/main/java/com/artemchep/keyguard/Main.kt | 4 +++- .../shared_prefs/SharedPrefsKeyValuePreference.kt | 8 ++++++++ .../shared_prefs/SharedPrefsKeyValueStore.kt | 12 +++++------- .../service/keyvalue/impl/JsonKeyValueStore.kt | 6 ++++++ .../keyguard/common/worker/impl/WrkerImpl.kt | 9 +++++++-- .../jvmMain/kotlin/com/artemchep/keyguard/Main.kt | 5 ++++- 6 files changed, 33 insertions(+), 11 deletions(-) diff --git a/androidApp/src/main/java/com/artemchep/keyguard/Main.kt b/androidApp/src/main/java/com/artemchep/keyguard/Main.kt index 1d3a638a..fdd2b9be 100644 --- a/androidApp/src/main/java/com/artemchep/keyguard/Main.kt +++ b/androidApp/src/main/java/com/artemchep/keyguard/Main.kt @@ -154,7 +154,9 @@ class Main : BaseApp(), DIAware { } else { null } - keyReadWriteRepository.put(persistedSession).bind() + keyReadWriteRepository.put(persistedSession) + .attempt() + .bind() } .collect() } diff --git a/common/src/androidMain/kotlin/db_key_value/shared_prefs/SharedPrefsKeyValuePreference.kt b/common/src/androidMain/kotlin/db_key_value/shared_prefs/SharedPrefsKeyValuePreference.kt index 426ad51c..99b3bcca 100644 --- a/common/src/androidMain/kotlin/db_key_value/shared_prefs/SharedPrefsKeyValuePreference.kt +++ b/common/src/androidMain/kotlin/db_key_value/shared_prefs/SharedPrefsKeyValuePreference.kt @@ -6,6 +6,7 @@ import com.artemchep.keyguard.common.service.keyvalue.KeyValuePreference import com.fredporciuncula.flow.preferences.Preference import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flow import kotlinx.coroutines.sync.Mutex @@ -13,6 +14,8 @@ import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext class SharedPrefsKeyValuePreference( + private val key: String, + private val defaultValue: T, private val prefFactory: suspend () -> Preference, ) : KeyValuePreference { private var pref: Preference? = null @@ -34,6 +37,11 @@ class SharedPrefsKeyValuePreference( override suspend fun collect(collector: FlowCollector) { flowOfPref() + // This should never happen. If it does it would crash the + // app, so instead we just fall back to the default value. + .catch { + emit(defaultValue) + } .distinctUntilChanged() .collect(collector) } diff --git a/common/src/androidMain/kotlin/db_key_value/shared_prefs/SharedPrefsKeyValueStore.kt b/common/src/androidMain/kotlin/db_key_value/shared_prefs/SharedPrefsKeyValueStore.kt index 79b92c19..635dd49c 100644 --- a/common/src/androidMain/kotlin/db_key_value/shared_prefs/SharedPrefsKeyValueStore.kt +++ b/common/src/androidMain/kotlin/db_key_value/shared_prefs/SharedPrefsKeyValueStore.kt @@ -7,11 +7,9 @@ import com.artemchep.keyguard.common.io.map import com.artemchep.keyguard.common.service.keyvalue.KeyValuePreference import com.artemchep.keyguard.common.service.keyvalue.KeyValueStore import com.fredporciuncula.flow.preferences.FlowSharedPreferences -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -@OptIn(ExperimentalCoroutinesApi::class) class SharedPrefsKeyValueStore( private val createPrefs: suspend () -> SharedPreferences, ) : KeyValueStore { @@ -43,27 +41,27 @@ class SharedPrefsKeyValueStore( .map { it.keys } override fun getInt(key: String, defaultValue: Int): KeyValuePreference = - SharedPrefsKeyValuePreference { + SharedPrefsKeyValuePreference(key, defaultValue) { getFlowPrefs().getInt(key, defaultValue) } override fun getFloat(key: String, defaultValue: Float): KeyValuePreference = - SharedPrefsKeyValuePreference { + SharedPrefsKeyValuePreference(key, defaultValue) { getFlowPrefs().getFloat(key, defaultValue) } override fun getBoolean(key: String, defaultValue: Boolean): KeyValuePreference = - SharedPrefsKeyValuePreference { + SharedPrefsKeyValuePreference(key, defaultValue) { getFlowPrefs().getBoolean(key, defaultValue) } override fun getLong(key: String, defaultValue: Long): KeyValuePreference = - SharedPrefsKeyValuePreference { + SharedPrefsKeyValuePreference(key, defaultValue) { getFlowPrefs().getLong(key, defaultValue) } override fun getString(key: String, defaultValue: String): KeyValuePreference = - SharedPrefsKeyValuePreference { + SharedPrefsKeyValuePreference(key, defaultValue) { getFlowPrefs().getString(key, defaultValue) } } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/keyvalue/impl/JsonKeyValueStore.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/keyvalue/impl/JsonKeyValueStore.kt index 83a3c307..fe1466f1 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/keyvalue/impl/JsonKeyValueStore.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/service/keyvalue/impl/JsonKeyValueStore.kt @@ -21,6 +21,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map @@ -97,6 +98,11 @@ class JsonKeyValueStore( val value = it[key] as? T value ?: default } + // This should never happen. If it does it would crash the + // app, so instead we just fall back to the default value. + .catch { + emit(default) + } .distinctUntilChanged() .collect(collector) } diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/worker/impl/WrkerImpl.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/worker/impl/WrkerImpl.kt index cbc71f7d..8b30ba2a 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/common/worker/impl/WrkerImpl.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/common/worker/impl/WrkerImpl.kt @@ -1,6 +1,7 @@ package com.artemchep.keyguard.common.worker.impl import com.artemchep.keyguard.android.downloader.journal.DownloadRepository +import com.artemchep.keyguard.common.io.attempt import com.artemchep.keyguard.common.io.bind import com.artemchep.keyguard.common.model.MasterSession import com.artemchep.keyguard.common.model.PersistedSession @@ -92,7 +93,9 @@ class WrkerImpl( } else { null } - keyReadWriteRepository.put(persistedSession).bind() + keyReadWriteRepository.put(persistedSession) + .attempt() + .bind() } .collect() } @@ -119,7 +122,9 @@ class WrkerImpl( } else { null } - keyReadWriteRepository.put(persistedSession).bind() + keyReadWriteRepository.put(persistedSession) + .attempt() + .bind() } .collect() } diff --git a/desktopApp/src/jvmMain/kotlin/com/artemchep/keyguard/Main.kt b/desktopApp/src/jvmMain/kotlin/com/artemchep/keyguard/Main.kt index f9e7561d..06f20f98 100644 --- a/desktopApp/src/jvmMain/kotlin/com/artemchep/keyguard/Main.kt +++ b/desktopApp/src/jvmMain/kotlin/com/artemchep/keyguard/Main.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.window.isTraySupported import androidx.compose.ui.window.rememberTrayState import androidx.compose.ui.window.rememberWindowState import com.artemchep.keyguard.common.AppWorker +import com.artemchep.keyguard.common.io.attempt import com.artemchep.keyguard.common.io.bind import com.artemchep.keyguard.common.model.MasterSession import com.artemchep.keyguard.common.model.PersistedSession @@ -178,7 +179,9 @@ fun main() { } else { null } - keyReadWriteRepository.put(persistedSession).bind() + keyReadWriteRepository.put(persistedSession) + .attempt() + .bind() } .launchIn(GlobalScope)