fix: rethrow UI preference transform IO failures

This commit is contained in:
2026-08-26 07:42:55 +08:00
parent 79b47fc354
commit 686176b148
2 changed files with 24 additions and 1 deletions
@@ -38,9 +38,16 @@ class DataStoreUiPreferencesRepository internal constructor(
transform: (UiPreferences) -> UiPreferences, transform: (UiPreferences) -> UiPreferences,
): UiPreferencesWriteResult = try { ): UiPreferencesWriteResult = try {
dataStore.edit { storedPreferences -> dataStore.edit { storedPreferences ->
storedPreferences.putAll(transform(preferencesFrom(storedPreferences))) val updatedPreferences = try {
transform(preferencesFrom(storedPreferences))
} catch (cause: Throwable) {
throw TransformFailure(cause)
}
storedPreferences.putAll(updatedPreferences)
} }
UiPreferencesWriteResult.Success UiPreferencesWriteResult.Success
} catch (failure: TransformFailure) {
throw failure.cause
} catch (cause: CancellationException) { } catch (cause: CancellationException) {
throw cause throw cause
} catch (_: IOException) { } catch (_: IOException) {
@@ -71,6 +78,10 @@ class DataStoreUiPreferencesRepository internal constructor(
private inline fun <reified T : Enum<T>> String.enumOrDefault(default: T): T = private inline fun <reified T : Enum<T>> String.enumOrDefault(default: T): T =
enumValues<T>().firstOrNull { it.name == this } ?: default enumValues<T>().firstOrNull { it.name == this } ?: default
private class TransformFailure(
override val cause: Throwable,
) : RuntimeException(cause)
private companion object { private companion object {
val RENDERER = stringPreferencesKey("renderer") val RENDERER = stringPreferencesKey("renderer")
val THEME_MODE = stringPreferencesKey("theme_mode") val THEME_MODE = stringPreferencesKey("theme_mode")
@@ -99,6 +99,18 @@ class DataStoreUiPreferencesRepositoryTest {
assertEquals(failure, actual) assertEquals(failure, actual)
} }
@Test
fun updateRethrowsTransformIOException() = runTest {
val repository = DataStoreUiPreferencesRepository(InMemoryPreferencesDataStore())
val failure = IOException("invalid transform")
val actual = runCatching {
repository.update { throw failure }
}.exceptionOrNull()
assertEquals(failure, actual)
}
@Test @Test
fun updateRethrowsCancellationException() = runTest { fun updateRethrowsCancellationException() = runTest {
val cancellation = CancellationException("cancelled") val cancellation = CancellationException("cancelled")