diff --git a/core/room/src/androidMain/kotlin/moe/lava/banksia/core/room/DatabaseManager.android.kt b/core/room/src/androidMain/kotlin/moe/lava/banksia/core/room/DatabaseManager.android.kt new file mode 100644 index 0000000..999ee4b --- /dev/null +++ b/core/room/src/androidMain/kotlin/moe/lava/banksia/core/room/DatabaseManager.android.kt @@ -0,0 +1,22 @@ +package moe.lava.banksia.core.room + +import android.content.Context +import androidx.room.Room +import org.koin.core.component.KoinComponent +import org.koin.core.component.get +import org.koin.core.component.inject + +actual class DatabaseManager actual constructor() : KoinComponent { + private val ctx by inject() + + actual val database by lazy { + val ctx = get().applicationContext + val dbFile = ctx.getDatabasePath("room.db") + val builder = Room.databaseBuilder( + context = ctx, + name = dbFile.absolutePath, + ) + + Database.build(builder) + } +} diff --git a/core/room/src/androidMain/kotlin/moe/lava/banksia/core/room/RoomDiModule.android.kt b/core/room/src/androidMain/kotlin/moe/lava/banksia/core/room/RoomDiModule.android.kt deleted file mode 100644 index 8cd01e6..0000000 --- a/core/room/src/androidMain/kotlin/moe/lava/banksia/core/room/RoomDiModule.android.kt +++ /dev/null @@ -1,21 +0,0 @@ -package moe.lava.banksia.core.room - -import android.content.Context -import androidx.room.Room -import androidx.room.RoomDatabase -import org.koin.core.parameter.ParametersHolder -import org.koin.core.scope.Scope - -class AndroidDatabaseBuilder(val ctx: Context) : PlatformDatabaseBuilder { - override fun getBuilder(): RoomDatabase.Builder { - val appContext = ctx.applicationContext - val dbFile = appContext.getDatabasePath("room.db") - return Room.databaseBuilder( - context = appContext, - name = dbFile.absolutePath - ) - } -} - -internal actual fun Scope.provideDatabaseBuilder(p: ParametersHolder): PlatformDatabaseBuilder = - AndroidDatabaseBuilder(get()) diff --git a/core/room/src/commonMain/kotlin/moe/lava/banksia/core/room/DatabaseManager.kt b/core/room/src/commonMain/kotlin/moe/lava/banksia/core/room/DatabaseManager.kt new file mode 100644 index 0000000..bfe32a9 --- /dev/null +++ b/core/room/src/commonMain/kotlin/moe/lava/banksia/core/room/DatabaseManager.kt @@ -0,0 +1,7 @@ +package moe.lava.banksia.core.room + +import org.koin.core.component.KoinComponent + +expect class DatabaseManager() : KoinComponent { + val database: Database +} diff --git a/core/room/src/commonMain/kotlin/moe/lava/banksia/core/room/RoomDiModule.kt b/core/room/src/commonMain/kotlin/moe/lava/banksia/core/room/RoomDiModule.kt index 67d4fd2..85c56fc 100644 --- a/core/room/src/commonMain/kotlin/moe/lava/banksia/core/room/RoomDiModule.kt +++ b/core/room/src/commonMain/kotlin/moe/lava/banksia/core/room/RoomDiModule.kt @@ -1,26 +1,18 @@ package moe.lava.banksia.core.room -import androidx.room.RoomDatabase -import org.koin.core.parameter.ParametersHolder -import org.koin.core.scope.Scope +import org.koin.core.module.dsl.singleOf import org.koin.dsl.module val roomDiModule = module { - single { provideDatabaseBuilder(it) } - single { Database.build(get().getBuilder()) } + singleOf(::DatabaseManager) + factory { get().database } - single { get().versionMetadataDao } - single { get().routeDao } - single { get().serviceDao } - single { get().serviceExceptionDao } - single { get().shapeDao } - single { get().stopDao } - single { get().stopTimeDao } - single { get().tripDao } + factory { get().versionMetadataDao } + factory { get().routeDao } + factory { get().serviceDao } + factory { get().serviceExceptionDao } + factory { get().shapeDao } + factory { get().stopDao } + factory { get().stopTimeDao } + factory { get().tripDao } } - -internal interface PlatformDatabaseBuilder { - fun getBuilder(): RoomDatabase.Builder -} - -internal expect fun Scope.provideDatabaseBuilder(p: ParametersHolder): PlatformDatabaseBuilder diff --git a/core/room/src/iosMain/kotlin/moe/lava/banksia/core/room/DatabaseManager.ios.kt b/core/room/src/iosMain/kotlin/moe/lava/banksia/core/room/DatabaseManager.ios.kt new file mode 100644 index 0000000..34e370e --- /dev/null +++ b/core/room/src/iosMain/kotlin/moe/lava/banksia/core/room/DatabaseManager.ios.kt @@ -0,0 +1,8 @@ +package moe.lava.banksia.core.room + +import org.koin.core.component.KoinComponent + +actual class DatabaseManager actual constructor() : KoinComponent { + actual val database: Database + get() = TODO("Not yet implemented") +} diff --git a/core/room/src/iosMain/kotlin/moe/lava/banksia/core/room/RoomDiModule.ios.kt b/core/room/src/iosMain/kotlin/moe/lava/banksia/core/room/RoomDiModule.ios.kt deleted file mode 100644 index 3c74852..0000000 --- a/core/room/src/iosMain/kotlin/moe/lava/banksia/core/room/RoomDiModule.ios.kt +++ /dev/null @@ -1,14 +0,0 @@ -package moe.lava.banksia.core.room - -import androidx.room.RoomDatabase -import org.koin.core.parameter.ParametersHolder -import org.koin.core.scope.Scope - -class IosDatabaseBuilder() : PlatformDatabaseBuilder { - override fun getBuilder(): RoomDatabase.Builder { - TODO("Not yet implemented") - } -} - -internal actual fun Scope.provideDatabaseBuilder(p: ParametersHolder): PlatformDatabaseBuilder = - IosDatabaseBuilder() diff --git a/core/room/src/jvmMain/kotlin/moe/lava/banksia/core/room/DatabaseManager.jvm.kt b/core/room/src/jvmMain/kotlin/moe/lava/banksia/core/room/DatabaseManager.jvm.kt new file mode 100644 index 0000000..b686c58 --- /dev/null +++ b/core/room/src/jvmMain/kotlin/moe/lava/banksia/core/room/DatabaseManager.jvm.kt @@ -0,0 +1,69 @@ +package moe.lava.banksia.core.room + +import androidx.room.Room +import androidx.room.RoomDatabase +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import moe.lava.banksia.core.util.error +import org.koin.core.component.KoinComponent +import java.io.File +import kotlin.system.exitProcess + +actual class DatabaseManager : KoinComponent { + private var liveDatabase: Database = Database.build(getBuilder()) + actual val database get() = liveDatabase + + private fun getBuilder(path: String = "./data/room.db"): RoomDatabase.Builder { + val dbFile = File(path) + return Room.databaseBuilder( + name = dbFile.absolutePath, + ).setJournalMode(RoomDatabase.JournalMode.TRUNCATE) + } + + fun makeAlt() = Database.build(getBuilder("./data/room_alt.db")) + + private fun deleteAll(file: File): Boolean { + val r1 = file.delete() + val r2 = File(file.parentFile, file.name + ".lck").delete() + val r3 = File(file.parentFile, file.name + "-journal").delete() + return r1 && r2 && r3 + } + + private fun renameAll(from: File, to: File): Boolean { + val r1 = from.renameTo(to) + val r2 = File(from.parentFile, from.name + ".lck").renameTo(File(to.parentFile, to.name + ".lck")) + val r3 = File(from.parentFile, from.name + "-journal").renameTo(File(to.parentFile, to.name + "-journal")) + return r1 && r2 && r3 + } + + fun swap(scope: CoroutineScope = CoroutineScope(Dispatchers.IO)) { + val live = File("./data/room.db") + val alt = File("./data/room_alt.db") + val old = File("./data/room_old.db") + + if (!renameAll(live, old)) { + error("DatabaseManager", "Failed to rename database from live to old (${live.absolutePath} -> ${old.absolutePath})") + return + } + if (!renameAll(alt, live)) { + error("DatabaseManager", "Failed to rename database from alt to live, trying to undo.. (${alt.absolutePath} -> ${live.absolutePath})") + if (!live.renameTo(old)) { + error("DatabaseManager", "Failed to undo, critical failure, exiting..") + exitProcess(1) + } + return + } + val oldDatabase = liveDatabase + liveDatabase = Database.build(getBuilder()) + + scope.launch { + delay(5000) + if (!deleteAll(old)) { + error("DatabaseManager", "Failed to unlink old database, stray files! (${old.absolutePath})") + } + oldDatabase.close() + } + } +} diff --git a/core/room/src/jvmMain/kotlin/moe/lava/banksia/core/room/RoomDiModule.jvm.kt b/core/room/src/jvmMain/kotlin/moe/lava/banksia/core/room/RoomDiModule.jvm.kt deleted file mode 100644 index 38c35ce..0000000 --- a/core/room/src/jvmMain/kotlin/moe/lava/banksia/core/room/RoomDiModule.jvm.kt +++ /dev/null @@ -1,19 +0,0 @@ -package moe.lava.banksia.core.room - -import androidx.room.Room -import androidx.room.RoomDatabase -import org.koin.core.parameter.ParametersHolder -import org.koin.core.scope.Scope -import java.io.File - -class JvmDatabaseBuilder() : PlatformDatabaseBuilder { - override fun getBuilder(): RoomDatabase.Builder { - val dbFile = File("./data/room.db") - return Room.databaseBuilder( - name = dbFile.absolutePath, - ) - } -} - -internal actual fun Scope.provideDatabaseBuilder(p: ParametersHolder): PlatformDatabaseBuilder = - JvmDatabaseBuilder()