fix: Do not crash if the key value database is not available #538

This commit is contained in:
Artem Chepurnoy 2024-08-18 17:49:27 +03:00
parent c2c167d094
commit 79796c0656
No known key found for this signature in database
GPG Key ID: FAC37D0CF674043E
6 changed files with 33 additions and 11 deletions

View File

@ -154,7 +154,9 @@ class Main : BaseApp(), DIAware {
} else { } else {
null null
} }
keyReadWriteRepository.put(persistedSession).bind() keyReadWriteRepository.put(persistedSession)
.attempt()
.bind()
} }
.collect() .collect()
} }

View File

@ -6,6 +6,7 @@ import com.artemchep.keyguard.common.service.keyvalue.KeyValuePreference
import com.fredporciuncula.flow.preferences.Preference import com.fredporciuncula.flow.preferences.Preference
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
@ -13,6 +14,8 @@ import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
class SharedPrefsKeyValuePreference<T : Any>( class SharedPrefsKeyValuePreference<T : Any>(
private val key: String,
private val defaultValue: T,
private val prefFactory: suspend () -> Preference<T>, private val prefFactory: suspend () -> Preference<T>,
) : KeyValuePreference<T> { ) : KeyValuePreference<T> {
private var pref: Preference<T>? = null private var pref: Preference<T>? = null
@ -34,6 +37,11 @@ class SharedPrefsKeyValuePreference<T : Any>(
override suspend fun collect(collector: FlowCollector<T>) { override suspend fun collect(collector: FlowCollector<T>) {
flowOfPref() 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() .distinctUntilChanged()
.collect(collector) .collect(collector)
} }

View File

@ -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.KeyValuePreference
import com.artemchep.keyguard.common.service.keyvalue.KeyValueStore import com.artemchep.keyguard.common.service.keyvalue.KeyValueStore
import com.fredporciuncula.flow.preferences.FlowSharedPreferences import com.fredporciuncula.flow.preferences.FlowSharedPreferences
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
@OptIn(ExperimentalCoroutinesApi::class)
class SharedPrefsKeyValueStore( class SharedPrefsKeyValueStore(
private val createPrefs: suspend () -> SharedPreferences, private val createPrefs: suspend () -> SharedPreferences,
) : KeyValueStore { ) : KeyValueStore {
@ -43,27 +41,27 @@ class SharedPrefsKeyValueStore(
.map { it.keys } .map { it.keys }
override fun getInt(key: String, defaultValue: Int): KeyValuePreference<Int> = override fun getInt(key: String, defaultValue: Int): KeyValuePreference<Int> =
SharedPrefsKeyValuePreference { SharedPrefsKeyValuePreference(key, defaultValue) {
getFlowPrefs().getInt(key, defaultValue) getFlowPrefs().getInt(key, defaultValue)
} }
override fun getFloat(key: String, defaultValue: Float): KeyValuePreference<Float> = override fun getFloat(key: String, defaultValue: Float): KeyValuePreference<Float> =
SharedPrefsKeyValuePreference { SharedPrefsKeyValuePreference(key, defaultValue) {
getFlowPrefs().getFloat(key, defaultValue) getFlowPrefs().getFloat(key, defaultValue)
} }
override fun getBoolean(key: String, defaultValue: Boolean): KeyValuePreference<Boolean> = override fun getBoolean(key: String, defaultValue: Boolean): KeyValuePreference<Boolean> =
SharedPrefsKeyValuePreference { SharedPrefsKeyValuePreference(key, defaultValue) {
getFlowPrefs().getBoolean(key, defaultValue) getFlowPrefs().getBoolean(key, defaultValue)
} }
override fun getLong(key: String, defaultValue: Long): KeyValuePreference<Long> = override fun getLong(key: String, defaultValue: Long): KeyValuePreference<Long> =
SharedPrefsKeyValuePreference { SharedPrefsKeyValuePreference(key, defaultValue) {
getFlowPrefs().getLong(key, defaultValue) getFlowPrefs().getLong(key, defaultValue)
} }
override fun getString(key: String, defaultValue: String): KeyValuePreference<String> = override fun getString(key: String, defaultValue: String): KeyValuePreference<String> =
SharedPrefsKeyValuePreference { SharedPrefsKeyValuePreference(key, defaultValue) {
getFlowPrefs().getString(key, defaultValue) getFlowPrefs().getString(key, defaultValue)
} }
} }

View File

@ -21,6 +21,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
@ -97,6 +98,11 @@ class JsonKeyValueStore(
val value = it[key] as? T val value = it[key] as? T
value ?: default 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() .distinctUntilChanged()
.collect(collector) .collect(collector)
} }

View File

@ -1,6 +1,7 @@
package com.artemchep.keyguard.common.worker.impl package com.artemchep.keyguard.common.worker.impl
import com.artemchep.keyguard.android.downloader.journal.DownloadRepository 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.io.bind
import com.artemchep.keyguard.common.model.MasterSession import com.artemchep.keyguard.common.model.MasterSession
import com.artemchep.keyguard.common.model.PersistedSession import com.artemchep.keyguard.common.model.PersistedSession
@ -92,7 +93,9 @@ class WrkerImpl(
} else { } else {
null null
} }
keyReadWriteRepository.put(persistedSession).bind() keyReadWriteRepository.put(persistedSession)
.attempt()
.bind()
} }
.collect() .collect()
} }
@ -119,7 +122,9 @@ class WrkerImpl(
} else { } else {
null null
} }
keyReadWriteRepository.put(persistedSession).bind() keyReadWriteRepository.put(persistedSession)
.attempt()
.bind()
} }
.collect() .collect()
} }

View File

@ -19,6 +19,7 @@ import androidx.compose.ui.window.isTraySupported
import androidx.compose.ui.window.rememberTrayState import androidx.compose.ui.window.rememberTrayState
import androidx.compose.ui.window.rememberWindowState import androidx.compose.ui.window.rememberWindowState
import com.artemchep.keyguard.common.AppWorker 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.io.bind
import com.artemchep.keyguard.common.model.MasterSession import com.artemchep.keyguard.common.model.MasterSession
import com.artemchep.keyguard.common.model.PersistedSession import com.artemchep.keyguard.common.model.PersistedSession
@ -178,7 +179,9 @@ fun main() {
} else { } else {
null null
} }
keyReadWriteRepository.put(persistedSession).bind() keyReadWriteRepository.put(persistedSession)
.attempt()
.bind()
} }
.launchIn(GlobalScope) .launchIn(GlobalScope)