Skip to content

Commit a39ef73

Browse files
committed
refactor: Improve database connection handling and error checking
- In `AndroidSafeRepo`, introduce a private `noteQueries` getter that throws an `SQLiteException` if the database holder is null, ensuring safer access. - In `MainViewModel`: - Refactor `checkDbConnection` into a suspend function `hasDbConnection` that returns a boolean, improving control flow. - `launchNotes` is now a single coroutine launch that first checks `hasDbConnection` before proceeding. - Ensure UI navigation to the splash screen on database errors happens on the main dispatcher. - In `JvmCipherUtils`, use the more specific `java.sql.SQLException` for exception handling instead of the fully qualified name.
1 parent 5e82360 commit a39ef73

File tree

3 files changed

+18
-9
lines changed
  • core

3 files changed

+18
-9
lines changed

core/data/db-sqldelight/src/androidMain/kotlin/com/softartdev/notedelight/repository/AndroidSafeRepo.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.softartdev.notedelight.repository
22

33
import android.content.Context
4+
import android.database.sqlite.SQLiteException
45
import android.text.SpannableStringBuilder
56
import app.cash.sqldelight.db.QueryResult
67
import app.cash.sqldelight.db.SqlCursor
@@ -11,6 +12,7 @@ import com.softartdev.notedelight.db.NoteDAO
1112
import com.softartdev.notedelight.db.SqlDelightDbHolder
1213
import com.softartdev.notedelight.db.SqlDelightNoteDAO
1314
import com.softartdev.notedelight.model.PlatformSQLiteState
15+
import com.softartdev.notedelight.shared.db.NoteQueries
1416
import com.softartdev.notedelight.util.CoroutineDispatchers
1517

1618
class AndroidSafeRepo(
@@ -29,11 +31,14 @@ class AndroidSafeRepo(
2931
}
3032

3133
override val noteDAO: NoteDAO
32-
get() = SqlDelightNoteDAO({ databaseHolder!!.noteQueries }, coroutineDispatchers)
34+
get() = SqlDelightNoteDAO(::noteQueries, coroutineDispatchers)
3335

3436
override val dbPath: String
3537
get() = context.getDatabasePath(DB_NAME).absolutePath
3638

39+
private val noteQueries : NoteQueries
40+
get() = databaseHolder?.noteQueries ?: throw SQLiteException("dnHolder is null")
41+
3742
override suspend fun buildDbIfNeed(passphrase: CharSequence): SqlDelightDbHolder {
3843
var instance = databaseHolder
3944
if (instance == null) {

core/data/db-sqldelight/src/jvmMain/kotlin/com/softartdev/notedelight/db/JvmCipherUtils.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import java.nio.charset.StandardCharsets
1010
import java.sql.Connection
1111
import java.sql.DriverManager
1212
import java.sql.ResultSet
13+
import java.sql.SQLException
1314
import java.sql.Statement
1415

1516
object JvmCipherUtils {
@@ -28,7 +29,7 @@ object JvmCipherUtils {
2829
try {
2930
DriverManager.registerDriver(driver)
3031
logger.d { "SQLite JDBC driver (sqlite-jdbc-crypt) registered successfully" }
31-
} catch (e: java.sql.SQLException) {
32+
} catch (e: SQLException) {
3233
if (e.message?.contains("already registered") == true) {
3334
logger.d { "SQLite JDBC driver already registered" }
3435
} else {
@@ -52,7 +53,7 @@ object JvmCipherUtils {
5253
val driverClass = Class.forName(SQLITE_JDBC_DRIVER)
5354
val driver = driverClass.getDeclaredConstructor().newInstance() as java.sql.Driver
5455
val props = java.util.Properties()
55-
driver.connect(url, props) ?: throw java.sql.SQLException("Failed to connect to encrypted database")
56+
driver.connect(url, props) ?: throw SQLException("Failed to connect to encrypted database")
5657
} catch (e: Exception) {
5758
logger.e(e) { "Failed to create encrypted connection, falling back to DriverManager" }
5859
DriverManager.getConnection(url)

core/presentation/src/commonMain/kotlin/com/softartdev/notedelight/presentation/main/MainViewModel.kt

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import kotlinx.coroutines.flow.Flow
1616
import kotlinx.coroutines.flow.MutableStateFlow
1717
import kotlinx.coroutines.flow.StateFlow
1818
import kotlinx.coroutines.launch
19+
import kotlinx.coroutines.withContext
1920

2021
class MainViewModel(
2122
private val safeRepo: SafeRepo,
@@ -44,18 +45,20 @@ class MainViewModel(
4445
is MainAction.OnRefresh -> updateNotes()
4546
}
4647

47-
fun launchNotes() {
48-
checkDbConnection()
49-
if (job != null) return
48+
fun launchNotes() = viewModelScope.launch {
49+
if (!hasDbConnection()) return@launch
50+
if (job != null) return@launch
5051
updateNotes()
5152
}
5253

53-
private fun checkDbConnection() = viewModelScope.launch(coroutineDispatchers.io) {
54+
private suspend fun hasDbConnection(): Boolean {
5455
try {
55-
val count: Long = safeRepo.noteDAO.count()
56+
val count: Long = withContext(coroutineDispatchers.io) { safeRepo.noteDAO.count() }
5657
logger.d { "check DB connection, notes: $count" }
58+
return true
5759
} catch (throwable: Throwable) {
5860
handleError("Error checking DB connection", throwable)
61+
return false
5962
}
6063
}
6164

@@ -81,7 +84,7 @@ class MainViewModel(
8184

8285
private fun handleError(message: String, throwable: Throwable) {
8386
logger.e(message, throwable)
84-
if (isDbError(throwable)) {
87+
if (isDbError(throwable)) viewModelScope.launch(coroutineDispatchers.main) {
8588
router.navigateClearingBackStack(AppNavGraph.Splash)
8689
}
8790
mutableStateFlow.value = NoteListResult.Error(throwable.message)

0 commit comments

Comments
 (0)