Skip to content

Commit

Permalink
Use SQLDelight in Backup/Restore (#7295)
Browse files Browse the repository at this point in the history
* Use SQLDelight in Backup/Restore

* Use CoroutineWorker
  • Loading branch information
ghostbear authored Jun 12, 2022
1 parent 3c9f96d commit fd5da2d
Show file tree
Hide file tree
Showing 20 changed files with 551 additions and 273 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ package eu.kanade.tachiyomi.data.backup

import android.content.Context
import android.net.Uri
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.data.DatabaseHandler
import eu.kanade.data.toLong
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
Expand All @@ -14,23 +15,26 @@ import eu.kanade.tachiyomi.source.model.toSChapter
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import data.Mangas as DbManga

abstract class AbstractBackupManager(protected val context: Context) {

internal val db: DatabaseHelper = Injekt.get()
protected val handler: DatabaseHandler = Injekt.get()

internal val sourceManager: SourceManager = Injekt.get()
internal val trackManager: TrackManager = Injekt.get()
protected val preferences: PreferencesHelper = Injekt.get()

abstract fun createBackup(uri: Uri, flags: Int, isAutoBackup: Boolean): String
abstract suspend fun createBackup(uri: Uri, flags: Int, isAutoBackup: Boolean): String

/**
* Returns manga
*
* @return [Manga], null if not found
*/
internal fun getMangaFromDatabase(manga: Manga): Manga? =
db.getManga(manga.url, manga.source).executeAsBlocking()
internal suspend fun getMangaFromDatabase(url: String, source: Long): DbManga? {
return handler.awaitOneOrNull { mangasQueries.getMangaByUrlAndSource(url, source) }
}

/**
* Fetches chapter information.
Expand All @@ -56,36 +60,134 @@ abstract class AbstractBackupManager(protected val context: Context) {
*
* @return [Manga] from library
*/
protected fun getFavoriteManga(): List<Manga> =
db.getFavoriteMangas().executeAsBlocking()
protected suspend fun getFavoriteManga(): List<DbManga> {
return handler.awaitList { mangasQueries.getFavorites() }
}

/**
* Inserts manga and returns id
*
* @return id of [Manga], null if not found
*/
internal fun insertManga(manga: Manga): Long? =
db.insertManga(manga).executeAsBlocking().insertedId()
internal suspend fun insertManga(manga: Manga): Long {
return handler.awaitOne(true) {
mangasQueries.insert(
source = manga.source,
url = manga.url,
artist = manga.artist,
author = manga.author,
description = manga.description,
genre = manga.getGenres(),
title = manga.title,
status = manga.status.toLong(),
thumbnail_url = manga.thumbnail_url,
favorite = manga.favorite,
last_update = manga.last_update,
next_update = 0L,
initialized = manga.initialized,
viewer = manga.viewer_flags.toLong(),
chapter_flags = manga.chapter_flags.toLong(),
cover_last_modified = manga.cover_last_modified,
date_added = manga.date_added,
)
mangasQueries.selectLastInsertedRowId()
}
}

internal suspend fun updateManga(manga: Manga): Long {
handler.await(true) {
mangasQueries.update(
source = manga.source,
url = manga.url,
artist = manga.artist,
author = manga.author,
description = manga.description,
genre = manga.genre,
title = manga.title,
status = manga.status.toLong(),
thumbnailUrl = manga.thumbnail_url,
favorite = manga.favorite.toLong(),
lastUpdate = manga.last_update,
initialized = manga.initialized.toLong(),
viewer = manga.viewer_flags.toLong(),
chapterFlags = manga.chapter_flags.toLong(),
coverLastModified = manga.cover_last_modified,
dateAdded = manga.date_added,
mangaId = manga.id!!,
)
}
return manga.id!!
}

/**
* Inserts list of chapters
*/
protected fun insertChapters(chapters: List<Chapter>) {
db.insertChapters(chapters).executeAsBlocking()
protected suspend fun insertChapters(chapters: List<Chapter>) {
handler.await(true) {
chapters.forEach { chapter ->
chaptersQueries.insert(
chapter.manga_id!!,
chapter.url,
chapter.name,
chapter.scanlator,
chapter.read,
chapter.bookmark,
chapter.last_page_read.toLong(),
chapter.chapter_number,
chapter.source_order.toLong(),
chapter.date_fetch,
chapter.date_upload,
)
}
}
}

/**
* Updates a list of chapters
*/
protected fun updateChapters(chapters: List<Chapter>) {
db.updateChaptersBackup(chapters).executeAsBlocking()
protected suspend fun updateChapters(chapters: List<Chapter>) {
handler.await(true) {
chapters.forEach { chapter ->
chaptersQueries.update(
chapter.manga_id!!,
chapter.url,
chapter.name,
chapter.scanlator,
chapter.read.toLong(),
chapter.bookmark.toLong(),
chapter.last_page_read.toLong(),
chapter.chapter_number.toDouble(),
chapter.source_order.toLong(),
chapter.date_fetch,
chapter.date_upload,
chapter.id!!,
)
}
}
}

/**
* Updates a list of chapters with known database ids
*/
protected fun updateKnownChapters(chapters: List<Chapter>) {
db.updateKnownChaptersBackup(chapters).executeAsBlocking()
protected suspend fun updateKnownChapters(chapters: List<Chapter>) {
handler.await(true) {
chapters.forEach { chapter ->
chaptersQueries.update(
mangaId = null,
url = null,
name = null,
scanlator = null,
read = chapter.read.toLong(),
bookmark = chapter.bookmark.toLong(),
lastPageRead = chapter.last_page_read.toLong(),
chapterNumber = null,
sourceOrder = null,
dateFetch = null,
dateUpload = null,
chapterId = chapter.id!!,
)
}
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package eu.kanade.tachiyomi.data.backup

import android.content.Context
import android.net.Uri
import eu.kanade.data.DatabaseHandler
import eu.kanade.data.chapter.NoChaptersException
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.Track
Expand All @@ -20,7 +20,7 @@ import java.util.Locale

abstract class AbstractBackupRestore<T : AbstractBackupManager>(protected val context: Context, protected val notifier: BackupNotifier) {

protected val db: DatabaseHelper by injectLazy()
protected val handler: DatabaseHandler by injectLazy()
protected val trackManager: TrackManager by injectLazy()

var job: Job? = null
Expand Down Expand Up @@ -91,7 +91,22 @@ abstract class AbstractBackupRestore<T : AbstractBackupManager>(protected val co
if (service != null && service.isLogged) {
try {
val updatedTrack = service.refresh(track)
db.insertTrack(updatedTrack).executeAsBlocking()
handler.await {
manga_syncQueries.insert(
updatedTrack.manga_id,
updatedTrack.sync_id.toLong(),
updatedTrack.media_id,
updatedTrack.library_id,
updatedTrack.title,
updatedTrack.last_chapter_read.toDouble(),
updatedTrack.total_chapters.toLong(),
updatedTrack.status.toLong(),
updatedTrack.score,
updatedTrack.tracking_url,
updatedTrack.started_reading_date,
updatedTrack.finished_reading_date,
)
}
} catch (e: Exception) {
errors.add(Date() to "${manga.title} - ${e.message}")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package eu.kanade.tachiyomi.data.backup
import android.content.Context
import android.net.Uri
import androidx.core.net.toUri
import androidx.work.CoroutineWorker
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import com.hippo.unifile.UniFile
Expand All @@ -24,9 +24,9 @@ import uy.kohesive.injekt.api.get
import java.util.concurrent.TimeUnit

class BackupCreatorJob(private val context: Context, workerParams: WorkerParameters) :
Worker(context, workerParams) {
CoroutineWorker(context, workerParams) {

override fun doWork(): Result {
override suspend fun doWork(): Result {
val preferences = Injekt.get<PreferencesHelper>()
val notifier = BackupNotifier(context)
val uri = inputData.getString(LOCATION_URI_KEY)?.let { Uri.parse(it) }
Expand Down
Loading

0 comments on commit fd5da2d

Please sign in to comment.