mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-04 03:14:40 -05:00
Update H2
This commit is contained in:
@@ -70,11 +70,11 @@ exposed-jdbc = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "e
|
|||||||
exposed-javatime = { module = "org.jetbrains.exposed:exposed-java-time", version.ref = "exposed" }
|
exposed-javatime = { module = "org.jetbrains.exposed:exposed-java-time", version.ref = "exposed" }
|
||||||
exposed-kotlintime = { module = "org.jetbrains.exposed:exposed-kotlin-datetime", version.ref = "exposed" }
|
exposed-kotlintime = { module = "org.jetbrains.exposed:exposed-kotlin-datetime", version.ref = "exposed" }
|
||||||
postgres = "org.postgresql:postgresql:42.7.11"
|
postgres = "org.postgresql:postgresql:42.7.11"
|
||||||
h2 = "com.h2database:h2:1.4.200" # current database driver, can't update to h2 v2 without sql migration
|
h2 = "com.h2database:h2:2.4.240"
|
||||||
hikaricp = "com.zaxxer:HikariCP:7.0.2"
|
hikaricp = "com.zaxxer:HikariCP:7.0.2"
|
||||||
|
|
||||||
# Exposed Migrations
|
# Exposed Migrations
|
||||||
exposed-migrations = "com.github.Suwayomi:exposed-migrations:3.10.0"
|
exposed-migrations = "com.github.Suwayomi:exposed-migrations:3.10.1"
|
||||||
|
|
||||||
# Dependency Injection
|
# Dependency Injection
|
||||||
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
|
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.app.Application
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
import suwayomi.tachidesk.manga.impl.update.IUpdater
|
import suwayomi.tachidesk.manga.impl.update.IUpdater
|
||||||
|
import suwayomi.tachidesk.server.database.H2Migration
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -74,6 +75,14 @@ private fun migrateMangaDownloadDir(applicationDirs: ApplicationDirs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun migrateDatabaseToV24240(applicationDirs: ApplicationDirs) {
|
||||||
|
H2Migration.migrate(
|
||||||
|
applicationDirs.dataRoot,
|
||||||
|
"1.4.200",
|
||||||
|
"2.4.240",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private val MIGRATIONS =
|
private val MIGRATIONS =
|
||||||
listOf<Pair<String, (ApplicationDirs) -> Unit>>(
|
listOf<Pair<String, (ApplicationDirs) -> Unit>>(
|
||||||
"InitialMigration" to { applicationDirs ->
|
"InitialMigration" to { applicationDirs ->
|
||||||
@@ -83,6 +92,9 @@ private val MIGRATIONS =
|
|||||||
"FixGlobalUpdateScheduling" to {
|
"FixGlobalUpdateScheduling" to {
|
||||||
Injekt.get<IUpdater>().deleteLastAutomatedUpdateTimestamp()
|
Injekt.get<IUpdater>().deleteLastAutomatedUpdateTimestamp()
|
||||||
},
|
},
|
||||||
|
"MigrateDatabaseToV2.4.240" to { applicationDirs ->
|
||||||
|
migrateDatabaseToV24240(applicationDirs)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
fun runMigrations(applicationDirs: ApplicationDirs) {
|
fun runMigrations(applicationDirs: ApplicationDirs) {
|
||||||
|
|||||||
@@ -391,6 +391,8 @@ fun applicationSetup() {
|
|||||||
"Localization service initialized. Supported languages: ${LocalizationHelper.getSupportedLocales()}"
|
"Localization service initialized. Supported languages: ${LocalizationHelper.getSupportedLocales()}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runMigrations(applicationDirs)
|
||||||
|
|
||||||
databaseUp()
|
databaseUp()
|
||||||
|
|
||||||
LocalSource.register()
|
LocalSource.register()
|
||||||
@@ -440,8 +442,6 @@ fun applicationSetup() {
|
|||||||
ignoreInitialValue = false,
|
ignoreInitialValue = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
runMigrations(applicationDirs)
|
|
||||||
|
|
||||||
setLogLevelFor("org.eclipse.jetty", Level.OFF)
|
setLogLevelFor("org.eclipse.jetty", Level.OFF)
|
||||||
setLogLevelFor("com.zaxxer.hikari", Level.WARN)
|
setLogLevelFor("com.zaxxer.hikari", Level.WARN)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,163 @@
|
|||||||
|
package suwayomi.tachidesk.server.database
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.network.GET
|
||||||
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.get
|
||||||
|
import java.net.URLClassLoader
|
||||||
|
import java.nio.file.Path
|
||||||
|
import kotlin.io.path.Path
|
||||||
|
import kotlin.io.path.absolutePathString
|
||||||
|
import kotlin.io.path.copyTo
|
||||||
|
import kotlin.io.path.createDirectories
|
||||||
|
import kotlin.io.path.deleteExisting
|
||||||
|
import kotlin.io.path.div
|
||||||
|
import kotlin.io.path.exists
|
||||||
|
import kotlin.io.path.name
|
||||||
|
import kotlin.io.path.notExists
|
||||||
|
import kotlin.io.path.outputStream
|
||||||
|
|
||||||
|
object H2Migration {
|
||||||
|
private val logger = KotlinLogging.logger {}
|
||||||
|
|
||||||
|
private val client by lazy {
|
||||||
|
Injekt.get<NetworkHelper>().client
|
||||||
|
}
|
||||||
|
|
||||||
|
private const val TOOL_VERSION = "1.8"
|
||||||
|
|
||||||
|
private const val TOOL_URL =
|
||||||
|
"https://manticore-projects.com/download/H2MigrationTool-$TOOL_VERSION/H2MigrationTool-$TOOL_VERSION-all.jar"
|
||||||
|
|
||||||
|
private const val MAVEN_BASE =
|
||||||
|
"https://repo1.maven.org/maven2/com/h2database/h2"
|
||||||
|
|
||||||
|
fun migrate(
|
||||||
|
rootDir: String,
|
||||||
|
h2Old: String,
|
||||||
|
h2New: String,
|
||||||
|
) {
|
||||||
|
val dbBase = "$rootDir/database"
|
||||||
|
val mvStore = Path("$dbBase.mv.db")
|
||||||
|
if (mvStore.notExists()) {
|
||||||
|
logger.info { "No H2 database found. Skipping migration." }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val script = Path("$dbBase.${h2Old.substringAfterLast('.')}.sql")
|
||||||
|
|
||||||
|
// Backup original database.
|
||||||
|
val backup = Path("$dbBase.mv.db.${h2Old.substringAfterLast('.')}.backup")
|
||||||
|
mvStore.copyTo(backup, overwrite = true)
|
||||||
|
logger.info { "Created backup: ${backup.absolutePathString()}" }
|
||||||
|
|
||||||
|
val toolsDir = Path(rootDir) / "bin" / "h2-migration-tools"
|
||||||
|
val libsDir = toolsDir / "h2libs"
|
||||||
|
libsDir.createDirectories()
|
||||||
|
|
||||||
|
// Download migration tool
|
||||||
|
val migrationJar =
|
||||||
|
toolsDir.resolve("H2MigrationTool-$TOOL_VERSION-all.jar")
|
||||||
|
downloadIfNeeded(
|
||||||
|
TOOL_URL,
|
||||||
|
migrationJar,
|
||||||
|
)
|
||||||
|
downloadIfNeeded(
|
||||||
|
"$MAVEN_BASE/$h2Old/h2-$h2Old.jar",
|
||||||
|
libsDir.resolve("h2-$h2Old.bin"),
|
||||||
|
)
|
||||||
|
downloadIfNeeded(
|
||||||
|
"$MAVEN_BASE/$h2New/h2-$h2New.jar",
|
||||||
|
libsDir.resolve("h2-$h2New.bin"),
|
||||||
|
)
|
||||||
|
|
||||||
|
runMigrationTool(
|
||||||
|
migrationJar = migrationJar,
|
||||||
|
libsDir = libsDir,
|
||||||
|
mvStore = mvStore,
|
||||||
|
script = script,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Move database to proper path
|
||||||
|
val newDatabase = Path(rootDir, "database.${h2New.substringAfterLast('.')}.mv.db")
|
||||||
|
newDatabase.copyTo(mvStore, overwrite = true)
|
||||||
|
newDatabase.deleteExisting()
|
||||||
|
|
||||||
|
logger.info { "H2 migration completed successfully." }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun downloadIfNeeded(
|
||||||
|
url: String,
|
||||||
|
output: Path,
|
||||||
|
) {
|
||||||
|
if (output.exists()) {
|
||||||
|
logger.debug { "Already downloaded: ${output.name}" }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
client
|
||||||
|
.newCall(GET(url))
|
||||||
|
.execute()
|
||||||
|
.use { response ->
|
||||||
|
|
||||||
|
if (!response.isSuccessful) {
|
||||||
|
throw RuntimeException(
|
||||||
|
"Failed to download $url " +
|
||||||
|
"(HTTP ${response.code})",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
output.outputStream().use { out ->
|
||||||
|
response.body.byteStream().copyTo(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info { "Saved: ${output.absolutePathString()}" }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun runMigrationTool(
|
||||||
|
migrationJar: Path,
|
||||||
|
libsDir: Path,
|
||||||
|
mvStore: Path,
|
||||||
|
script: Path,
|
||||||
|
) {
|
||||||
|
URLClassLoader(
|
||||||
|
arrayOf(migrationJar.toUri().toURL()),
|
||||||
|
javaClass.classLoader,
|
||||||
|
).use { classLoader ->
|
||||||
|
val clazz =
|
||||||
|
classLoader.loadClass("com.manticore.h2.H2MigrationTool")
|
||||||
|
|
||||||
|
val main =
|
||||||
|
clazz.getMethod("main", Array<String>::class.java)
|
||||||
|
|
||||||
|
main.invoke(
|
||||||
|
null,
|
||||||
|
arrayOf(
|
||||||
|
// h2 driver dir
|
||||||
|
"-l",
|
||||||
|
libsDir.absolutePathString(),
|
||||||
|
// from version
|
||||||
|
"-f",
|
||||||
|
"1.4.200",
|
||||||
|
// to version
|
||||||
|
"-t",
|
||||||
|
"2.4.240",
|
||||||
|
// user
|
||||||
|
"-u",
|
||||||
|
"",
|
||||||
|
// password
|
||||||
|
"-p",
|
||||||
|
"",
|
||||||
|
// database.mv.db
|
||||||
|
"-d",
|
||||||
|
mvStore.absolutePathString(),
|
||||||
|
// database backup in SQL
|
||||||
|
"-s",
|
||||||
|
script.absolutePathString(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user