Make backup restoring logic more sequential

(cherry picked from commit aded11e5996161036e3df01bacecdacb30f3e34b)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestore.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupRestore.kt
This commit is contained in:
arkon 2021-02-12 12:19:12 -05:00 committed by Jobobby04
parent 2ff186eaec
commit 16f9ca381e
5 changed files with 63 additions and 65 deletions

View File

@ -42,9 +42,9 @@ abstract class AbstractBackupRestore<T : AbstractBackupManager>(protected val co
protected val errors = mutableListOf<Pair<Date, String>>() protected val errors = mutableListOf<Pair<Date, String>>()
abstract fun performRestore(uri: Uri): Boolean abstract suspend fun performRestore(uri: Uri): Boolean
fun restoreBackup(uri: Uri): Boolean { suspend fun restoreBackup(uri: Uri): Boolean {
val startTime = System.currentTimeMillis() val startTime = System.currentTimeMillis()
restoreProgress = 0 restoreProgress = 0
errors.clear() errors.clear()

View File

@ -14,7 +14,10 @@ import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.system.acquireWakeLock import eu.kanade.tachiyomi.util.system.acquireWakeLock
import eu.kanade.tachiyomi.util.system.isServiceRunning import eu.kanade.tachiyomi.util.system.isServiceRunning
import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
@ -68,12 +71,14 @@ class BackupRestoreService : Service() {
*/ */
private lateinit var wakeLock: PowerManager.WakeLock private lateinit var wakeLock: PowerManager.WakeLock
private lateinit var ioScope: CoroutineScope
private var backupRestore: AbstractBackupRestore<*>? = null private var backupRestore: AbstractBackupRestore<*>? = null
private lateinit var notifier: BackupNotifier private lateinit var notifier: BackupNotifier
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
ioScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
notifier = BackupNotifier(this) notifier = BackupNotifier(this)
wakeLock = acquireWakeLock(javaClass.name) wakeLock = acquireWakeLock(javaClass.name)
@ -92,6 +97,7 @@ class BackupRestoreService : Service() {
private fun destroyJob() { private fun destroyJob() {
backupRestore?.job?.cancel() backupRestore?.job?.cancel()
ioScope?.cancel()
if (wakeLock.isHeld) { if (wakeLock.isHeld) {
wakeLock.release() wakeLock.release()
} }
@ -122,6 +128,7 @@ class BackupRestoreService : Service() {
BackupConst.BACKUP_TYPE_FULL -> FullBackupRestore(this, notifier, online) BackupConst.BACKUP_TYPE_FULL -> FullBackupRestore(this, notifier, online)
else -> LegacyBackupRestore(this, notifier) else -> LegacyBackupRestore(this, notifier)
} }
val handler = CoroutineExceptionHandler { _, exception -> val handler = CoroutineExceptionHandler { _, exception ->
Timber.e(exception) Timber.e(exception)
backupRestore?.writeErrorLog() backupRestore?.writeErrorLog()
@ -129,14 +136,15 @@ class BackupRestoreService : Service() {
notifier.showRestoreError(exception.message) notifier.showRestoreError(exception.message)
stopSelf(startId) stopSelf(startId)
} }
backupRestore?.job = GlobalScope.launch(handler) { val job = ioScope.launch(handler) {
if (backupRestore?.restoreBackup(uri) == false) { if (backupRestore?.restoreBackup(uri) == false) {
notifier.showRestoreError(getString(R.string.restoring_backup_canceled)) notifier.showRestoreError(getString(R.string.restoring_backup_canceled))
} }
} }
backupRestore?.job?.invokeOnCompletion { job.invokeOnCompletion {
stopSelf(startId) stopSelf(startId)
} }
backupRestore?.job = job
return START_NOT_STICKY return START_NOT_STICKY
} }

View File

@ -17,7 +17,6 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.online.all.MergedSource import eu.kanade.tachiyomi.source.online.all.MergedSource
import eu.kanade.tachiyomi.util.lang.launchIO
import exh.EXHMigrations import exh.EXHMigrations
import exh.source.MERGED_SOURCE_ID import exh.source.MERGED_SOURCE_ID
import okio.buffer import okio.buffer
@ -27,7 +26,7 @@ import java.util.Date
class FullBackupRestore(context: Context, notifier: BackupNotifier, private val online: Boolean) : AbstractBackupRestore<FullBackupManager>(context, notifier) { class FullBackupRestore(context: Context, notifier: BackupNotifier, private val online: Boolean) : AbstractBackupRestore<FullBackupManager>(context, notifier) {
override fun performRestore(uri: Uri): Boolean { override suspend fun performRestore(uri: Uri): Boolean {
// SY --> // SY -->
throttleManager.resetThrottle() throttleManager.resetThrottle()
// SY <-- // SY <--
@ -82,7 +81,7 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val
} }
// SY <-- // SY <--
private fun restoreManga(backupManga: BackupManga, backupCategories: List<BackupCategory>, online: Boolean) { private suspend fun restoreManga(backupManga: BackupManga, backupCategories: List<BackupCategory>, online: Boolean) {
var manga = backupManga.getMangaImpl() var manga = backupManga.getMangaImpl()
val chapters = backupManga.getChaptersImpl() val chapters = backupManga.getChaptersImpl()
val categories = backupManga.categories val categories = backupManga.categories
@ -124,7 +123,7 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val
* @param history history data from json * @param history history data from json
* @param tracks tracking data from json * @param tracks tracking data from json
*/ */
private fun restoreMangaData( private suspend fun restoreMangaData(
manga: Manga, manga: Manga,
source: Source?, source: Source?,
chapters: List<Chapter>, chapters: List<Chapter>,
@ -158,7 +157,7 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val
* @param chapters chapters of manga that needs updating * @param chapters chapters of manga that needs updating
* @param categories categories that need updating * @param categories categories that need updating
*/ */
private fun restoreMangaFetch( private suspend fun restoreMangaFetch(
source: Source?, source: Source?,
manga: Manga, manga: Manga,
chapters: List<Chapter>, chapters: List<Chapter>,
@ -170,31 +169,29 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val
flatMetadata: BackupFlatMetadata?, flatMetadata: BackupFlatMetadata?,
online: Boolean online: Boolean
) { ) {
launchIO { try {
try { val fetchedManga = backupManager.restoreMangaFetch(source, manga, online)
val fetchedManga = backupManager.restoreMangaFetch(source, manga, online) fetchedManga.id ?: return
fetchedManga.id ?: (return@launchIO)
if (online && source != null) { if (online && source != null) {
// SY --> // SY -->
if (source !is MergedSource) { if (source !is MergedSource) {
updateChapters(source, fetchedManga, chapters) updateChapters(source, fetchedManga, chapters)
}
// SY <--
} else {
backupManager.restoreChaptersForMangaOffline(fetchedManga, chapters)
} }
// SY <--
restoreExtraForManga(fetchedManga, categories, history, tracks, backupCategories, mergedMangaReferences, flatMetadata) } else {
backupManager.restoreChaptersForMangaOffline(fetchedManga, chapters)
updateTracking(fetchedManga, tracks)
} catch (e: Exception) {
errors.add(Date() to "${manga.title} - ${e.message}")
} }
restoreExtraForManga(fetchedManga, categories, history, tracks, backupCategories, mergedMangaReferences, flatMetadata)
updateTracking(fetchedManga, tracks)
} catch (e: Exception) {
errors.add(Date() to "${manga.title} - ${e.message}")
} }
} }
private fun restoreMangaNoFetch( private suspend fun restoreMangaNoFetch(
source: Source?, source: Source?,
backupManga: Manga, backupManga: Manga,
chapters: List<Chapter>, chapters: List<Chapter>,
@ -206,19 +203,17 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val
flatMetadata: BackupFlatMetadata?, flatMetadata: BackupFlatMetadata?,
online: Boolean online: Boolean
) { ) {
launchIO { if (online && source != null) {
if (online && source != null) { if (/* SY --> */ source !is MergedSource && /* SY <-- */ !backupManager.restoreChaptersForManga(backupManga, chapters)) {
if (/* SY --> */ source !is MergedSource && /* SY <-- */ !backupManager.restoreChaptersForManga(backupManga, chapters)) { updateChapters(source, backupManga, chapters)
updateChapters(source, backupManga, chapters)
}
} else {
backupManager.restoreChaptersForMangaOffline(backupManga, chapters)
} }
} else {
restoreExtraForManga(backupManga, categories, history, tracks, backupCategories, mergedMangaReferences, flatMetadata) backupManager.restoreChaptersForMangaOffline(backupManga, chapters)
updateTracking(backupManga, tracks)
} }
restoreExtraForManga(backupManga, categories, history, tracks, backupCategories, mergedMangaReferences, flatMetadata)
updateTracking(backupManga, tracks)
} }
private suspend fun restoreExtraForManga(manga: Manga, categories: List<Int>, history: List<BackupHistory>, tracks: List<Track>, backupCategories: List<BackupCategory>, mergedMangaReferences: List<BackupMergedMangaReference>, flatMetadata: BackupFlatMetadata?) { private suspend fun restoreExtraForManga(manga: Manga, categories: List<Int>, history: List<BackupHistory>, tracks: List<Track>, backupCategories: List<BackupCategory>, mergedMangaReferences: List<BackupMergedMangaReference>, flatMetadata: BackupFlatMetadata?) {

View File

@ -21,13 +21,12 @@ import eu.kanade.tachiyomi.data.database.models.MangaImpl
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.database.models.TrackImpl import eu.kanade.tachiyomi.data.database.models.TrackImpl
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.util.lang.launchIO
import exh.EXHMigrations import exh.EXHMigrations
import java.util.Date import java.util.Date
class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : AbstractBackupRestore<LegacyBackupManager>(context, notifier) { class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : AbstractBackupRestore<LegacyBackupManager>(context, notifier) {
override fun performRestore(uri: Uri): Boolean { override suspend fun performRestore(uri: Uri): Boolean {
// SY --> // SY -->
throttleManager.resetThrottle() throttleManager.resetThrottle()
// SY <-- // SY <--
@ -91,7 +90,7 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract
} }
// SY <-- // SY <--
private fun restoreManga(mangaJson: JsonObject) { private suspend fun restoreManga(mangaJson: JsonObject) {
/* SY --> */ var /* SY <-- */ manga = backupManager.parser.fromJson<MangaImpl>( /* SY --> */ var /* SY <-- */ manga = backupManager.parser.fromJson<MangaImpl>(
mangaJson.get( mangaJson.get(
Backup.MANGA Backup.MANGA
@ -145,7 +144,7 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract
* @param history history data from json * @param history history data from json
* @param tracks tracking data from json * @param tracks tracking data from json
*/ */
private fun restoreMangaData( private suspend fun restoreMangaData(
manga: Manga, manga: Manga,
source: Source, source: Source,
chapters: List<Chapter>, chapters: List<Chapter>,
@ -175,7 +174,7 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract
* @param chapters chapters of manga that needs updating * @param chapters chapters of manga that needs updating
* @param categories categories that need updating * @param categories categories that need updating
*/ */
private fun restoreMangaFetch( private suspend fun restoreMangaFetch(
source: Source, source: Source,
manga: Manga, manga: Manga,
chapters: List<Chapter>, chapters: List<Chapter>,
@ -183,23 +182,21 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract
history: List<DHistory>, history: List<DHistory>,
tracks: List<Track> tracks: List<Track>
) { ) {
launchIO { try {
try { val fetchedManga = backupManager.fetchManga(source, manga)
val fetchedManga = backupManager.fetchManga(source, manga) fetchedManga.id ?: return
fetchedManga.id ?: (return@launchIO)
updateChapters(source, fetchedManga, chapters) updateChapters(source, fetchedManga, chapters)
restoreExtraForManga(fetchedManga, categories, history, tracks) restoreExtraForManga(fetchedManga, categories, history, tracks)
updateTracking(fetchedManga, tracks) updateTracking(fetchedManga, tracks)
} catch (e: Exception) { } catch (e: Exception) {
errors.add(Date() to "${manga.title} - ${e.message}") errors.add(Date() to "${manga.title} - ${e.message}")
}
} }
} }
private fun restoreMangaNoFetch( private suspend fun restoreMangaNoFetch(
source: Source, source: Source,
backupManga: Manga, backupManga: Manga,
chapters: List<Chapter>, chapters: List<Chapter>,
@ -207,15 +204,13 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract
history: List<DHistory>, history: List<DHistory>,
tracks: List<Track> tracks: List<Track>
) { ) {
launchIO { if (!backupManager.restoreChaptersForManga(backupManga, chapters)) {
if (!backupManager.restoreChaptersForManga(backupManga, chapters)) { updateChapters(source, backupManga, chapters)
updateChapters(source, backupManga, chapters)
}
restoreExtraForManga(backupManga, categories, history, tracks)
updateTracking(backupManga, tracks)
} }
restoreExtraForManga(backupManga, categories, history, tracks)
updateTracking(backupManga, tracks)
} }
private fun restoreExtraForManga(manga: Manga, categories: List<String>, history: List<DHistory>, tracks: List<Track>) { private fun restoreExtraForManga(manga: Manga, categories: List<String>, history: List<DHistory>, tracks: List<Track>) {

View File

@ -193,8 +193,8 @@ class LibraryUpdateService(
* lock. * lock.
*/ */
override fun onDestroy() { override fun onDestroy() {
ioScope?.cancel()
updateJob?.cancel() updateJob?.cancel()
ioScope?.cancel()
if (wakeLock.isHeld) { if (wakeLock.isHeld) {
wakeLock.release() wakeLock.release()
} }