Fix sync stalled

This commit is contained in:
Jobobby04 2024-03-25 18:32:27 -04:00
parent fb1649125c
commit edca9039e5
7 changed files with 53 additions and 13 deletions

View File

@ -50,7 +50,7 @@ class SyncSettingsSelector : Screen() {
actionLabel = stringResource(MR.strings.label_sync), actionLabel = stringResource(MR.strings.label_sync),
actionEnabled = state.options.anyEnabled(), actionEnabled = state.options.anyEnabled(),
onClickAction = { onClickAction = {
if (!SyncDataJob.isAnyJobRunning(context)) { if (!SyncDataJob.isRunning(context)) {
model.syncNow(context) model.syncNow(context)
navigator.pop() navigator.pop()
} else { } else {

View File

@ -43,7 +43,7 @@ class SyncTriggerOptionsScreen : Screen() {
LazyColumnWithAction( LazyColumnWithAction(
contentPadding = contentPadding, contentPadding = contentPadding,
actionLabel = stringResource(MR.strings.action_save), actionLabel = stringResource(MR.strings.action_save),
actionEnabled = state.options.anyEnabled(), actionEnabled = true,
onClickAction = { onClickAction = {
navigator.pop() navigator.pop()
}, },

View File

@ -823,7 +823,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
// Always sync the data before library update if syncing is enabled. // Always sync the data before library update if syncing is enabled.
if (syncPreferences.isSyncEnabled()) { if (syncPreferences.isSyncEnabled()) {
// Check if SyncDataJob is already running // Check if SyncDataJob is already running
if (wm.isRunning(SyncDataJob.TAG_MANUAL)) { if (SyncDataJob.isRunning(context)) {
// SyncDataJob is already running // SyncDataJob is already running
return false return false
} }

View File

@ -9,11 +9,14 @@ import androidx.work.ExistingWorkPolicy
import androidx.work.ForegroundInfo import androidx.work.ForegroundInfo
import androidx.work.OneTimeWorkRequestBuilder import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.PeriodicWorkRequestBuilder import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkInfo
import androidx.work.WorkQuery
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import eu.kanade.domain.sync.SyncPreferences import eu.kanade.domain.sync.SyncPreferences
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.system.cancelNotification import eu.kanade.tachiyomi.util.system.cancelNotification
import eu.kanade.tachiyomi.util.system.isRunning import eu.kanade.tachiyomi.util.system.isRunning
import eu.kanade.tachiyomi.util.system.setForegroundSafely
import eu.kanade.tachiyomi.util.system.workManager import eu.kanade.tachiyomi.util.system.workManager
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.common.util.system.logcat import tachiyomi.core.common.util.system.logcat
@ -27,12 +30,15 @@ class SyncDataJob(private val context: Context, workerParams: WorkerParameters)
private val notifier = SyncNotifier(context) private val notifier = SyncNotifier(context)
override suspend fun doWork(): Result { override suspend fun doWork(): Result {
try { if (tags.contains(TAG_AUTO)) {
setForeground(getForegroundInfo()) // Find a running manual worker. If exists, try again later
} catch (e: IllegalStateException) { if (context.workManager.isRunning(TAG_MANUAL)) {
logcat(LogPriority.ERROR, e) { "Not allowed to run on foreground service" } return Result.retry()
}
} }
setForegroundSafely()
return try { return try {
SyncManager(context).syncData() SyncManager(context).syncData()
Result.success() Result.success()
@ -62,10 +68,8 @@ class SyncDataJob(private val context: Context, workerParams: WorkerParameters)
private const val TAG_AUTO = "$TAG_JOB:auto" private const val TAG_AUTO = "$TAG_JOB:auto"
const val TAG_MANUAL = "$TAG_JOB:manual" const val TAG_MANUAL = "$TAG_JOB:manual"
private val jobTagList = listOf(TAG_AUTO, TAG_MANUAL) fun isRunning(context: Context): Boolean {
return context.workManager.isRunning(TAG_JOB)
fun isAnyJobRunning(context: Context): Boolean {
return jobTagList.any { context.workManager.isRunning(it) }
} }
fun setupTask(context: Context, prefInterval: Int? = null) { fun setupTask(context: Context, prefInterval: Int? = null) {
@ -79,6 +83,7 @@ class SyncDataJob(private val context: Context, workerParams: WorkerParameters)
10, 10,
TimeUnit.MINUTES, TimeUnit.MINUTES,
) )
.addTag(TAG_JOB)
.addTag(TAG_AUTO) .addTag(TAG_AUTO)
.build() .build()
@ -89,14 +94,33 @@ class SyncDataJob(private val context: Context, workerParams: WorkerParameters)
} }
fun startNow(context: Context) { fun startNow(context: Context) {
val wm = context.workManager
if (wm.isRunning(TAG_JOB)) {
// Already running either as a scheduled or manual job
return
}
val request = OneTimeWorkRequestBuilder<SyncDataJob>() val request = OneTimeWorkRequestBuilder<SyncDataJob>()
.addTag(TAG_JOB)
.addTag(TAG_MANUAL) .addTag(TAG_MANUAL)
.build() .build()
context.workManager.enqueueUniqueWork(TAG_MANUAL, ExistingWorkPolicy.KEEP, request) context.workManager.enqueueUniqueWork(TAG_MANUAL, ExistingWorkPolicy.KEEP, request)
} }
fun stop(context: Context) { fun stop(context: Context) {
context.workManager.cancelUniqueWork(TAG_MANUAL) val wm = context.workManager
val workQuery = WorkQuery.Builder.fromTags(listOf(TAG_JOB, TAG_AUTO, TAG_MANUAL))
.addStates(listOf(WorkInfo.State.RUNNING))
.build()
wm.getWorkInfos(workQuery).get()
// Should only return one work but just in case
.forEach {
wm.cancelWorkById(it.id)
// Re-enqueue cancelled scheduled work
if (it.tags.contains(TAG_AUTO)) {
setupTask(context)
}
}
} }
} }
} }

View File

@ -164,7 +164,7 @@ object LibraryTab : Tab {
} }
}, },
onClickSyncNow = { onClickSyncNow = {
if (!SyncDataJob.isAnyJobRunning(context)) { if (!SyncDataJob.isRunning(context)) {
SyncDataJob.startNow(context) SyncDataJob.startNow(context)
} else { } else {
context.toast(MR.strings.sync_in_progress) context.toast(MR.strings.sync_in_progress)

View File

@ -13,6 +13,7 @@ import eu.kanade.tachiyomi.core.security.SecurityPreferences
import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob
import eu.kanade.tachiyomi.data.cache.PagePreviewCache import eu.kanade.tachiyomi.data.cache.PagePreviewCache
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.sync.SyncDataJob
import eu.kanade.tachiyomi.data.track.TrackerManager import eu.kanade.tachiyomi.data.track.TrackerManager
import eu.kanade.tachiyomi.network.NetworkPreferences import eu.kanade.tachiyomi.network.NetworkPreferences
import eu.kanade.tachiyomi.network.PREF_DOH_CLOUDFLARE import eu.kanade.tachiyomi.network.PREF_DOH_CLOUDFLARE
@ -114,6 +115,7 @@ object EXHMigrations {
LibraryUpdateJob.setupTask(context) LibraryUpdateJob.setupTask(context)
BackupCreateJob.setupTask(context) BackupCreateJob.setupTask(context)
EHentaiUpdateWorker.scheduleBackground(context) EHentaiUpdateWorker.scheduleBackground(context)
SyncDataJob.setupTask(context)
// Fresh install // Fresh install
if (oldVersion == 0) { if (oldVersion == 0) {

View File

@ -9,6 +9,8 @@ import eu.kanade.domain.ui.UiPreferences
import eu.kanade.tachiyomi.core.security.SecurityPreferences import eu.kanade.tachiyomi.core.security.SecurityPreferences
import eu.kanade.tachiyomi.data.backup.models.Backup import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.data.cache.PagePreviewCache import eu.kanade.tachiyomi.data.cache.PagePreviewCache
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.sync.SyncDataJob
import eu.kanade.tachiyomi.data.track.TrackerManager import eu.kanade.tachiyomi.data.track.TrackerManager
import eu.kanade.tachiyomi.network.NetworkPreferences import eu.kanade.tachiyomi.network.NetworkPreferences
import eu.kanade.tachiyomi.source.AndroidSourceManager import eu.kanade.tachiyomi.source.AndroidSourceManager
@ -36,6 +38,8 @@ import tachiyomi.domain.manga.interactor.GetFlatMetadataById
import tachiyomi.domain.manga.interactor.GetSearchMetadata import tachiyomi.domain.manga.interactor.GetSearchMetadata
import tachiyomi.domain.manga.interactor.InsertFlatMetadata import tachiyomi.domain.manga.interactor.InsertFlatMetadata
import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.util.UUID import java.util.UUID
@ -340,4 +344,14 @@ object DebugFunctions {
} }
fun exportProtobufScheme() = ProtoBufSchemaGenerator.generateSchemaText(Backup.serializer().descriptor) fun exportProtobufScheme() = ProtoBufSchemaGenerator.generateSchemaText(Backup.serializer().descriptor)
fun killSyncJobs() {
val context = Injekt.get<Application>()
SyncDataJob.stop(context)
}
fun killLibraryJobs() {
val context = Injekt.get<Application>()
LibraryUpdateJob.stop(context)
}
} }