From aded11e5996161036e3df01bacecdacb30f3e34b Mon Sep 17 00:00:00 2001 From: arkon Date: Fri, 12 Feb 2021 12:19:12 -0500 Subject: [PATCH] Make backup restoring logic more sequential --- .../data/backup/AbstractBackupRestore.kt | 4 +- .../data/backup/BackupRestoreService.kt | 14 ++++- .../data/backup/full/FullBackupRestore.kt | 59 +++++++++---------- .../data/backup/legacy/LegacyBackupRestore.kt | 43 ++++++-------- .../data/library/LibraryUpdateService.kt | 2 +- 5 files changed, 60 insertions(+), 62 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupRestore.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupRestore.kt index 31d3b6ccc..10fa5bd31 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupRestore.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupRestore.kt @@ -37,9 +37,9 @@ abstract class AbstractBackupRestore(protected val co protected val errors = mutableListOf>() - 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() restoreProgress = 0 errors.clear() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt index 10320b602..d057792dc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt @@ -14,7 +14,10 @@ import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.util.system.acquireWakeLock import eu.kanade.tachiyomi.util.system.isServiceRunning 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 timber.log.Timber @@ -68,12 +71,14 @@ class BackupRestoreService : Service() { */ private lateinit var wakeLock: PowerManager.WakeLock + private lateinit var ioScope: CoroutineScope private var backupRestore: AbstractBackupRestore<*>? = null private lateinit var notifier: BackupNotifier override fun onCreate() { super.onCreate() + ioScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) notifier = BackupNotifier(this) wakeLock = acquireWakeLock(javaClass.name) @@ -92,6 +97,7 @@ class BackupRestoreService : Service() { private fun destroyJob() { backupRestore?.job?.cancel() + ioScope?.cancel() if (wakeLock.isHeld) { wakeLock.release() } @@ -122,6 +128,7 @@ class BackupRestoreService : Service() { BackupConst.BACKUP_TYPE_FULL -> FullBackupRestore(this, notifier, online) else -> LegacyBackupRestore(this, notifier) } + val handler = CoroutineExceptionHandler { _, exception -> Timber.e(exception) backupRestore?.writeErrorLog() @@ -129,14 +136,15 @@ class BackupRestoreService : Service() { notifier.showRestoreError(exception.message) stopSelf(startId) } - backupRestore?.job = GlobalScope.launch(handler) { + val job = ioScope.launch(handler) { if (backupRestore?.restoreBackup(uri) == false) { notifier.showRestoreError(getString(R.string.restoring_backup_canceled)) } } - backupRestore?.job?.invokeOnCompletion { + job.invokeOnCompletion { stopSelf(startId) } + backupRestore?.job = job return START_NOT_STICKY } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestore.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestore.kt index ce306f26c..f6cbb72eb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestore.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupRestore.kt @@ -13,7 +13,6 @@ import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.source.Source -import eu.kanade.tachiyomi.util.lang.launchIO import okio.buffer import okio.gzip import okio.source @@ -21,7 +20,7 @@ import java.util.Date class FullBackupRestore(context: Context, notifier: BackupNotifier, private val online: Boolean) : AbstractBackupRestore(context, notifier) { - override fun performRestore(uri: Uri): Boolean { + override suspend fun performRestore(uri: Uri): Boolean { backupManager = FullBackupManager(context) val backupString = context.contentResolver.openInputStream(uri)!!.source().gzip().buffer().use { it.readByteArray() } @@ -58,7 +57,7 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val showRestoreProgress(restoreProgress, restoreAmount, context.getString(R.string.categories)) } - private fun restoreManga(backupManga: BackupManga, backupCategories: List, online: Boolean) { + private suspend fun restoreManga(backupManga: BackupManga, backupCategories: List, online: Boolean) { val manga = backupManga.getMangaImpl() val chapters = backupManga.getChaptersImpl() val categories = backupManga.categories @@ -92,7 +91,7 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val * @param history history data from json * @param tracks tracking data from json */ - private fun restoreMangaData( + private suspend fun restoreMangaData( manga: Manga, source: Source?, chapters: List, @@ -124,7 +123,7 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val * @param chapters chapters of manga that needs updating * @param categories categories that need updating */ - private fun restoreMangaFetch( + private suspend fun restoreMangaFetch( source: Source?, manga: Manga, chapters: List, @@ -134,27 +133,25 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val backupCategories: List, online: Boolean ) { - launchIO { - try { - val fetchedManga = backupManager.restoreMangaFetch(source, manga, online) - fetchedManga.id ?: (return@launchIO) + try { + val fetchedManga = backupManager.restoreMangaFetch(source, manga, online) + fetchedManga.id ?: return - if (online && source != null) { - updateChapters(source, fetchedManga, chapters) - } else { - backupManager.restoreChaptersForMangaOffline(fetchedManga, chapters) - } - - restoreExtraForManga(fetchedManga, categories, history, tracks, backupCategories) - - updateTracking(fetchedManga, tracks) - } catch (e: Exception) { - errors.add(Date() to "${manga.title} - ${e.message}") + if (online && source != null) { + updateChapters(source, fetchedManga, chapters) + } else { + backupManager.restoreChaptersForMangaOffline(fetchedManga, chapters) } + + restoreExtraForManga(fetchedManga, categories, history, tracks, backupCategories) + + updateTracking(fetchedManga, tracks) + } catch (e: Exception) { + errors.add(Date() to "${manga.title} - ${e.message}") } } - private fun restoreMangaNoFetch( + private suspend fun restoreMangaNoFetch( source: Source?, backupManga: Manga, chapters: List, @@ -164,19 +161,17 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val backupCategories: List, online: Boolean ) { - launchIO { - if (online && source != null) { - if (!backupManager.restoreChaptersForManga(backupManga, chapters)) { - updateChapters(source, backupManga, chapters) - } - } else { - backupManager.restoreChaptersForMangaOffline(backupManga, chapters) + if (online && source != null) { + if (!backupManager.restoreChaptersForManga(backupManga, chapters)) { + updateChapters(source, backupManga, chapters) } - - restoreExtraForManga(backupManga, categories, history, tracks, backupCategories) - - updateTracking(backupManga, tracks) + } else { + backupManager.restoreChaptersForMangaOffline(backupManga, chapters) } + + restoreExtraForManga(backupManga, categories, history, tracks, backupCategories) + + updateTracking(backupManga, tracks) } private fun restoreExtraForManga(manga: Manga, categories: List, history: List, tracks: List, backupCategories: List) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupRestore.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupRestore.kt index b910155c8..5d11f8c5a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupRestore.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/LegacyBackupRestore.kt @@ -21,12 +21,11 @@ import eu.kanade.tachiyomi.data.database.models.MangaImpl import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.TrackImpl import eu.kanade.tachiyomi.source.Source -import eu.kanade.tachiyomi.util.lang.launchIO import java.util.Date class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : AbstractBackupRestore(context, notifier) { - override fun performRestore(uri: Uri): Boolean { + override suspend fun performRestore(uri: Uri): Boolean { val reader = JsonReader(context.contentResolver.openInputStream(uri)!!.bufferedReader()) val json = JsonParser.parseReader(reader).asJsonObject @@ -63,7 +62,7 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract showRestoreProgress(restoreProgress, restoreAmount, context.getString(R.string.categories)) } - private fun restoreManga(mangaJson: JsonObject) { + private suspend fun restoreManga(mangaJson: JsonObject) { val manga = backupManager.parser.fromJson( mangaJson.get( Backup.MANGA @@ -113,7 +112,7 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract * @param history history data from json * @param tracks tracking data from json */ - private fun restoreMangaData( + private suspend fun restoreMangaData( manga: Manga, source: Source, chapters: List, @@ -143,7 +142,7 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract * @param chapters chapters of manga that needs updating * @param categories categories that need updating */ - private fun restoreMangaFetch( + private suspend fun restoreMangaFetch( source: Source, manga: Manga, chapters: List, @@ -151,23 +150,21 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract history: List, tracks: List ) { - launchIO { - try { - val fetchedManga = backupManager.fetchManga(source, manga) - fetchedManga.id ?: (return@launchIO) + try { + val fetchedManga = backupManager.fetchManga(source, manga) + fetchedManga.id ?: return - updateChapters(source, fetchedManga, chapters) + updateChapters(source, fetchedManga, chapters) - restoreExtraForManga(fetchedManga, categories, history, tracks) + restoreExtraForManga(fetchedManga, categories, history, tracks) - updateTracking(fetchedManga, tracks) - } catch (e: Exception) { - errors.add(Date() to "${manga.title} - ${e.message}") - } + updateTracking(fetchedManga, tracks) + } catch (e: Exception) { + errors.add(Date() to "${manga.title} - ${e.message}") } } - private fun restoreMangaNoFetch( + private suspend fun restoreMangaNoFetch( source: Source, backupManga: Manga, chapters: List, @@ -175,15 +172,13 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract history: List, tracks: List ) { - launchIO { - if (!backupManager.restoreChaptersForManga(backupManga, chapters)) { - updateChapters(source, backupManga, chapters) - } - - restoreExtraForManga(backupManga, categories, history, tracks) - - updateTracking(backupManga, tracks) + if (!backupManager.restoreChaptersForManga(backupManga, chapters)) { + updateChapters(source, backupManga, chapters) } + + restoreExtraForManga(backupManga, categories, history, tracks) + + updateTracking(backupManga, tracks) } private fun restoreExtraForManga(manga: Manga, categories: List, history: List, tracks: List) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt index c049ba263..6a1cbf2b3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt @@ -158,8 +158,8 @@ class LibraryUpdateService( * lock. */ override fun onDestroy() { - ioScope?.cancel() updateJob?.cancel() + ioScope?.cancel() if (wakeLock.isHeld) { wakeLock.release() }