Compare commits

...

3 Commits

Author SHA1 Message Date
Cologler
93fd498864 chore: optimize chapter query 2024-04-09 20:58:25 +08:00
Cologler
0a7678b41a chore: optimize excluded_scanlators query 2024-04-09 20:06:40 +08:00
Cologler
f919e7d4b9 chore: optimize history query 2024-04-09 19:55:58 +08:00
5 changed files with 90 additions and 48 deletions

View File

@@ -8,10 +8,11 @@ import eu.kanade.tachiyomi.data.backup.models.BackupTracking
import eu.kanade.tachiyomi.data.backup.models.backupChapterMapper
import eu.kanade.tachiyomi.data.backup.models.backupTrackMapper
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
import logcat.LogPriority
import tachiyomi.core.common.util.system.logcat
import tachiyomi.data.DatabaseHandler
import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.category.model.Category
import tachiyomi.domain.history.interactor.GetHistory
import tachiyomi.domain.manga.model.Manga
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@@ -19,51 +20,77 @@ import uy.kohesive.injekt.api.get
class MangaBackupCreator(
private val handler: DatabaseHandler = Injekt.get(),
private val getCategories: GetCategories = Injekt.get(),
private val getHistory: GetHistory = Injekt.get(),
) {
suspend fun backupMangas(mangas: List<Manga>, options: BackupOptions): List<BackupManga> {
val categoriesMap = if (options.categories) {
getCategories.awaitWithMangaId()
} else {
emptyMap()
if (mangas.isEmpty()) {
// skip all other SQL queries
return emptyList()
}
val trackingMap = if (options.tracking) {
val excludedScanlatorsMap = handler.awaitList {
excluded_scanlatorsQueries.listAll { mangaId, scanlator ->
Pair(mangaId, scanlator)
}
}.groupBy({ it.first }, { it.second })
logcat(LogPriority.DEBUG) { "Begin load chapters" }
val chaptersMap = if (options.chapters) {
handler.awaitList {
chaptersQueries.listAll(backupChapterMapper)
}.groupBy({ it.first }, { it.second })
} else emptyMap()
logcat(LogPriority.DEBUG) { "End load chapters, found ${chaptersMap.values.sumOf { it.size }}" }
val categoriesMap = if (options.categories) {
getCategories.awaitWithMangaId()
} else emptyMap()
val tracksMap = if (options.tracking) {
handler.awaitList {
manga_syncQueries.getTracks(backupTrackMapper)
}.groupBy({ it.first }, { it.second })
} else {
emptyMap()
}
} else emptyMap()
val historiesMap = if (options.history) {
handler.awaitList {
historyQueries.listHistoriesWithMangaId { mangaId, url, lastRead, timeRead ->
Pair(mangaId, BackupHistory(url, lastRead?.time ?: 0L, timeRead))
}
}.groupBy({ it.first }, { it.second })
} else emptyMap()
return mangas.map {
backupManga(it, options, categoriesMap, trackingMap)
backupManga(it, options,
excludedScanlatorsMap,
chaptersMap,
categoriesMap,
tracksMap,
historiesMap)
}
}
private suspend fun backupManga(
private fun backupManga(
manga: Manga,
options: BackupOptions,
excludedScanlatorsMap: Map<Long, List<String>>,
chaptersMap: Map<Long, List<BackupChapter>>,
categoriesMap: Map<Long, List<Category>>,
trackingMap: Map<Long, List<BackupTracking>>
tracksMap: Map<Long, List<BackupTracking>>,
historiesMap: Map<Long, List<BackupHistory>>
): BackupManga {
// Entry for this manga
val mangaObject = manga.toBackupManga()
mangaObject.excludedScanlators = handler.awaitList {
excluded_scanlatorsQueries.getExcludedScanlatorsByMangaId(manga.id)
excludedScanlatorsMap[manga.id]?.let {
mangaObject.excludedScanlators = it
}
if (options.chapters) {
// Backup all the chapters
handler.awaitList {
chaptersQueries.getChaptersByMangaId(
mangaId = manga.id,
applyScanlatorFilter = 0, // false
mapper = backupChapterMapper,
)
}
.takeUnless(List<BackupChapter>::isEmpty)
chaptersMap[manga.id]
?.takeUnless(List<BackupChapter>::isNullOrEmpty)
?.let { mangaObject.chapters = it }
}
@@ -76,22 +103,16 @@ class MangaBackupCreator(
}
if (options.tracking) {
val tracks = trackingMap[manga.id]
val tracks = tracksMap[manga.id]
if (tracks?.isNotEmpty() == true) {
mangaObject.tracking = tracks
}
}
if (options.history) {
val historyByMangaId = getHistory.await(manga.id)
if (historyByMangaId.isNotEmpty()) {
val history = historyByMangaId.map { history ->
val chapter = handler.awaitOne { chaptersQueries.getChapterById(history.chapterId) }
BackupHistory(chapter.url, history.readAt?.time ?: 0L, history.readDuration)
}
if (history.isNotEmpty()) {
mangaObject.history = history
}
val history = historiesMap[manga.id]
if (history?.isNotEmpty() == true) {
mangaObject.history = history
}
}

View File

@@ -44,7 +44,7 @@ data class BackupChapter(
val backupChapterMapper = {
_: Long,
_: Long,
mangaId: Long,
url: String,
name: String,
scanlator: String?,
@@ -59,18 +59,21 @@ val backupChapterMapper = {
version: Long,
_: Long,
->
BackupChapter(
url = url,
name = name,
chapterNumber = chapterNumber.toFloat(),
scanlator = scanlator,
read = read,
bookmark = bookmark,
lastPageRead = lastPageRead,
dateFetch = dateFetch,
dateUpload = dateUpload,
sourceOrder = sourceOrder,
lastModifiedAt = lastModifiedAt,
version = version,
Pair(
mangaId,
BackupChapter(
url = url,
name = name,
chapterNumber = chapterNumber.toFloat(),
scanlator = scanlator,
read = read,
bookmark = bookmark,
lastPageRead = lastPageRead,
dateFetch = dateFetch,
dateUpload = dateUpload,
sourceOrder = sourceOrder,
lastModifiedAt = lastModifiedAt,
version = version,
)
)
}

View File

@@ -118,4 +118,8 @@ SET manga_id = coalesce(:mangaId, manga_id),
WHERE _id = :chapterId;
selectLastInsertedRowId:
SELECT last_insert_rowid();
SELECT last_insert_rowid();
listAll:
SELECT *
FROM chapters;

View File

@@ -20,3 +20,7 @@ getExcludedScanlatorsByMangaId:
SELECT scanlator
FROM excluded_scanlators
WHERE manga_id = :mangaId;
listAll:
SELECT *
FROM excluded_scanlators;

View File

@@ -71,3 +71,13 @@ WHERE chapter_id = :chapterId;
getReadDuration:
SELECT coalesce(sum(time_read), 0)
FROM history;
listHistoriesWithMangaId:
SELECT
C.manga_id mangaId,
C.url,
H.last_read,
H.time_read
FROM history H
JOIN chapters C
ON H.chapter_id = C._id;