fix sqlite locking fuckery by replacing it with h2

This commit is contained in:
Aria Moradi 2021-02-04 00:32:01 +03:30
parent 172f83f5b3
commit d766206343
6 changed files with 130 additions and 172 deletions

View File

@ -80,6 +80,8 @@ dependencies {
implementation ("org.jetbrains.exposed:exposed-dao:$exposed_version") implementation ("org.jetbrains.exposed:exposed-dao:$exposed_version")
implementation ("org.jetbrains.exposed:exposed-jdbc:$exposed_version") implementation ("org.jetbrains.exposed:exposed-jdbc:$exposed_version")
implementation ("org.xerial:sqlite-jdbc:3.30.1") implementation ("org.xerial:sqlite-jdbc:3.30.1")
implementation ("com.h2database:h2:1.4.199")
// AndroidCompat // AndroidCompat
implementation(project(":AndroidCompat")) implementation(project(":AndroidCompat"))

View File

@ -11,7 +11,7 @@ import ir.armor.tachidesk.util.getChapterList
import ir.armor.tachidesk.util.getExtensionList import ir.armor.tachidesk.util.getExtensionList
import ir.armor.tachidesk.util.getManga import ir.armor.tachidesk.util.getManga
import ir.armor.tachidesk.util.getMangaList import ir.armor.tachidesk.util.getMangaList
import ir.armor.tachidesk.util.getMangaUpdateQueueThread // import ir.armor.tachidesk.util.getMangaUpdateQueueThread
import ir.armor.tachidesk.util.getPages import ir.armor.tachidesk.util.getPages
import ir.armor.tachidesk.util.getSource import ir.armor.tachidesk.util.getSource
import ir.armor.tachidesk.util.getSourceList import ir.armor.tachidesk.util.getSourceList
@ -57,7 +57,7 @@ class Main {
// start app // start app
androidCompat.startApp(App()) androidCompat.startApp(App())
Thread(getMangaUpdateQueueThread).start() // Thread(getMangaUpdateQueueThread).start()
val app = Javalin.create { config -> val app = Javalin.create { config ->
try { try {

View File

@ -15,13 +15,15 @@ import org.jetbrains.exposed.sql.transactions.transaction
object DBMangaer { object DBMangaer {
val db by lazy { val db by lazy {
Database.connect("jdbc:sqlite:${Config.dataRoot}/database.db", "org.sqlite.JDBC") Database.connect("jdbc:h2:${Config.dataRoot}/database.h2", "org.h2.Driver")
// Database.connect("jdbc:sqlite:${Config.dataRoot}/database.sqlite3", "org.sqlite.JDBC")
} }
} }
fun makeDataBaseTables() { fun makeDataBaseTables() {
// mention db object to connect // mention db object to connect
DBMangaer.db val db = DBMangaer.db
db.useNestedTransactions = true
transaction { transaction {
SchemaUtils.create(ExtensionsTable) SchemaUtils.create(ExtensionsTable)

View File

@ -12,62 +12,15 @@ import ir.armor.tachidesk.database.table.MangaStatus
import ir.armor.tachidesk.database.table.MangaTable import ir.armor.tachidesk.database.table.MangaTable
import ir.armor.tachidesk.database.table.SourceTable import ir.armor.tachidesk.database.table.SourceTable
import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update import org.jetbrains.exposed.sql.update
import java.io.File import java.io.File
import java.io.InputStream import java.io.InputStream
import java.util.concurrent.ArrayBlockingQueue
val getMangaUpdateQueue = ArrayBlockingQueue<Pair<Int, SManga?>>(1000)
@Volatile
var getMangaCount = 0
val getMangaUpdateQueueThread = Runnable {
while (true) {
val p = getMangaUpdateQueue.take()
println("took ${p.first}")
while (getMangaCount > 0) {
println("count is $getMangaCount")
Thread.sleep(1000)
}
val mangaId = p.first
println("working on $mangaId")
val fetchedManga = p.second!!
try {
transaction {
println("transaction start $mangaId")
MangaTable.update({ MangaTable.id eq mangaId }) {
it[MangaTable.initialized] = true
it[MangaTable.artist] = fetchedManga.artist
it[MangaTable.author] = fetchedManga.author
it[MangaTable.description] = fetchedManga.description
it[MangaTable.genre] = fetchedManga.genre
it[MangaTable.status] = fetchedManga.status
if (fetchedManga.thumbnail_url != null && fetchedManga.thumbnail_url!!.isNotEmpty())
it[MangaTable.thumbnail_url] = fetchedManga.thumbnail_url
}
println("transaction end $mangaId")
}
} catch (e: Exception) {
println(e)
}
}
}
fun getManga(mangaId: Int, proxyThumbnail: Boolean = true): MangaDataClass { fun getManga(mangaId: Int, proxyThumbnail: Boolean = true): MangaDataClass {
synchronized(getMangaCount) { var mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! }
getMangaCount++
}
return try {
transaction {
var mangaEntry = MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!!
return@transaction if (mangaEntry[MangaTable.initialized]) { return if (mangaEntry[MangaTable.initialized]) {
println("${mangaEntry[MangaTable.title]} is initialized")
println("${mangaEntry[MangaTable.thumbnail_url]}")
MangaDataClass( MangaDataClass(
mangaId, mangaId,
mangaEntry[MangaTable.sourceReference].value, mangaEntry[MangaTable.sourceReference].value,
@ -93,16 +46,23 @@ fun getManga(mangaId: Int, proxyThumbnail: Boolean = true): MangaDataClass {
} }
).toBlocking().first() ).toBlocking().first()
// update database transaction {
// TODO: sqlite gets fucked here MangaTable.update({ MangaTable.id eq mangaId }) {
println("putting $mangaId")
getMangaUpdateQueue.put(Pair(mangaId, fetchedManga))
// mangaEntry = MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! it[MangaTable.initialized] = true
val newThumbnail =
if (fetchedManga.thumbnail_url != null && fetchedManga.thumbnail_url!!.isNotEmpty()) { it[MangaTable.artist] = fetchedManga.artist
fetchedManga.thumbnail_url it[MangaTable.author] = fetchedManga.author
} else mangaEntry[MangaTable.thumbnail_url] it[MangaTable.description] = fetchedManga.description
it[MangaTable.genre] = fetchedManga.genre
it[MangaTable.status] = fetchedManga.status
if (fetchedManga.thumbnail_url != null && fetchedManga.thumbnail_url!!.isNotEmpty())
it[MangaTable.thumbnail_url] = fetchedManga.thumbnail_url
}
}
mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! }
val newThumbnail = mangaEntry[MangaTable.thumbnail_url]
MangaDataClass( MangaDataClass(
mangaId, mangaId,
@ -121,23 +81,16 @@ fun getManga(mangaId: Int, proxyThumbnail: Boolean = true): MangaDataClass {
MangaStatus.valueOf(fetchedManga.status).name, MangaStatus.valueOf(fetchedManga.status).name,
) )
} }
}
} finally {
synchronized(getMangaCount) {
getMangaCount--
}
}
} }
fun getThumbnail(mangaId: Int): Pair<InputStream, String> { fun getThumbnail(mangaId: Int): Pair<InputStream, String> {
return transaction { val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! }
var mangaEntry = MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!!
var filePath = Config.thumbnailsRoot + "/$mangaId" var filePath = Config.thumbnailsRoot + "/$mangaId"
val potentialCache = findFileNameStartingWith(Config.thumbnailsRoot, mangaId.toString()) val potentialCache = findFileNameStartingWith(Config.thumbnailsRoot, mangaId.toString())
if (potentialCache != null) { if (potentialCache != null) {
println("using cached thumbnail file") println("using cached thumbnail file")
return@transaction Pair( return Pair(
pathToInputStream(potentialCache), pathToInputStream(potentialCache),
"image/${potentialCache.substringAfter("$mangaId.")}" "image/${potentialCache.substringAfter("$mangaId.")}"
) )
@ -163,14 +116,13 @@ fun getThumbnail(mangaId: Int): Pair<InputStream, String> {
writeStream(response.body!!.byteStream(), filePath) writeStream(response.body!!.byteStream(), filePath)
return@transaction Pair( return Pair(
pathToInputStream(filePath), pathToInputStream(filePath),
contentType contentType
) )
} else { } else {
throw Exception("request error! ${response.code}") throw Exception("request error! ${response.code}")
} }
}
} }
fun getMangaDir(mangaId: Int): String { fun getMangaDir(mangaId: Int): String {

View File

@ -1,13 +1,15 @@
package ir.armor.tachidesk.util package ir.armor.tachidesk.util
import com.android.dx.util.ExceptionWithContext.withContext
import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import kotlinx.coroutines.Dispatchers
import okhttp3.FormBody import okhttp3.FormBody
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import java.net.URLEncoder import java.net.URLEncoder
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
class MangaDexHelper(private val mangaDexSource: HttpSource) { class MangaDexHelper(private val mangaDexSource: HttpSource) {
private fun clientBuilder(): OkHttpClient = clientBuilder(0) private fun clientBuilder(): OkHttpClient = clientBuilder(0)