mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Make backup restoring logic more sequential
This commit is contained in:
		@@ -37,9 +37,9 @@ abstract class AbstractBackupRestore<T : AbstractBackupManager>(protected val co
 | 
			
		||||
 | 
			
		||||
    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()
 | 
			
		||||
        restoreProgress = 0
 | 
			
		||||
        errors.clear()
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -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<FullBackupManager>(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<BackupCategory>, online: Boolean) {
 | 
			
		||||
    private suspend fun restoreManga(backupManga: BackupManga, backupCategories: List<BackupCategory>, 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<Chapter>,
 | 
			
		||||
@@ -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<Chapter>,
 | 
			
		||||
@@ -134,27 +133,25 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val
 | 
			
		||||
        backupCategories: List<BackupCategory>,
 | 
			
		||||
        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<Chapter>,
 | 
			
		||||
@@ -164,19 +161,17 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val
 | 
			
		||||
        backupCategories: List<BackupCategory>,
 | 
			
		||||
        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<Int>, history: List<BackupHistory>, tracks: List<Track>, backupCategories: List<BackupCategory>) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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<LegacyBackupManager>(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<MangaImpl>(
 | 
			
		||||
            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<Chapter>,
 | 
			
		||||
@@ -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<Chapter>,
 | 
			
		||||
@@ -151,23 +150,21 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract
 | 
			
		||||
        history: List<DHistory>,
 | 
			
		||||
        tracks: List<Track>
 | 
			
		||||
    ) {
 | 
			
		||||
        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<Chapter>,
 | 
			
		||||
@@ -175,15 +172,13 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract
 | 
			
		||||
        history: List<DHistory>,
 | 
			
		||||
        tracks: List<Track>
 | 
			
		||||
    ) {
 | 
			
		||||
        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<String>, history: List<DHistory>, tracks: List<Track>) {
 | 
			
		||||
 
 | 
			
		||||
@@ -158,8 +158,8 @@ class LibraryUpdateService(
 | 
			
		||||
     * lock.
 | 
			
		||||
     */
 | 
			
		||||
    override fun onDestroy() {
 | 
			
		||||
        ioScope?.cancel()
 | 
			
		||||
        updateJob?.cancel()
 | 
			
		||||
        ioScope?.cancel()
 | 
			
		||||
        if (wakeLock.isHeld) {
 | 
			
		||||
            wakeLock.release()
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user