Fix tracker operations parallelism

pull/488/head
Koitharu 3 years ago
parent d1b0af85c4
commit d3e4e97c6f
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -110,21 +110,26 @@ class Tracker @Inject constructor(
private fun compare(track: MangaTracking, manga: Manga, branch: String?): MangaUpdates.Success { private fun compare(track: MangaTracking, manga: Manga, branch: String?): MangaUpdates.Success {
if (track.isEmpty()) { if (track.isEmpty()) {
// first check or manga was empty on last check // first check or manga was empty on last check
return MangaUpdates.Success(manga, emptyList(), isValid = false) return MangaUpdates.Success(manga, emptyList(), isValid = false, channelId = null)
} }
val chapters = requireNotNull(manga.getChapters(branch)) val chapters = requireNotNull(manga.getChapters(branch))
val newChapters = chapters.takeLastWhile { x -> x.id != track.lastChapterId } val newChapters = chapters.takeLastWhile { x -> x.id != track.lastChapterId }
return when { return when {
newChapters.isEmpty() -> { newChapters.isEmpty() -> {
MangaUpdates.Success(manga, emptyList(), isValid = chapters.lastOrNull()?.id == track.lastChapterId) MangaUpdates.Success(
manga = manga,
newChapters = emptyList(),
isValid = chapters.lastOrNull()?.id == track.lastChapterId,
channelId = null
)
} }
newChapters.size == chapters.size -> { newChapters.size == chapters.size -> {
MangaUpdates.Success(manga, emptyList(), isValid = false) MangaUpdates.Success(manga, emptyList(), isValid = false, channelId = null)
} }
else -> { else -> {
MangaUpdates.Success(manga, newChapters, isValid = true) MangaUpdates.Success(manga, newChapters, isValid = true, channelId = null)
} }
} }
} }

@ -8,16 +8,17 @@ sealed interface MangaUpdates {
val manga: Manga val manga: Manga
class Success( data class Success(
override val manga: Manga, override val manga: Manga,
val newChapters: List<MangaChapter>, val newChapters: List<MangaChapter>,
val isValid: Boolean, val isValid: Boolean,
val channelId: String?,
) : MangaUpdates { ) : MangaUpdates {
fun isNotEmpty() = newChapters.isNotEmpty() fun isNotEmpty() = newChapters.isNotEmpty()
} }
class Failure( data class Failure(
override val manga: Manga, override val manga: Manga,
val error: Throwable?, val error: Throwable?,
) : MangaUpdates { ) : MangaUpdates {

@ -39,6 +39,7 @@ import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.channelFlow import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.toList import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runInterruptible import kotlinx.coroutines.runInterruptible
@ -148,19 +149,9 @@ class TrackWorker @AssistedInject constructor(
send( send(
runCatchingCancellable { runCatchingCancellable {
tracker.fetchUpdates(track, commit = true) tracker.fetchUpdates(track, commit = true)
.copy(channelId = channelId)
}.onFailure { e -> }.onFailure { e ->
if (e is CloudFlareProtectedException) {
CaptchaNotifier(applicationContext).notify(e)
}
logger.log("checkUpdatesAsync", e) logger.log("checkUpdatesAsync", e)
}.onSuccess { updates ->
if (updates.isValid && updates.isNotEmpty()) {
showNotification(
manga = updates.manga,
channelId = channelId,
newChapters = updates.newChapters,
)
}
}.getOrElse { error -> }.getOrElse { error ->
MangaUpdates.Failure( MangaUpdates.Failure(
manga = track.manga, manga = track.manga,
@ -171,10 +162,33 @@ class TrackWorker @AssistedInject constructor(
} }
} }
} }
}.onEach {
when (it) {
is MangaUpdates.Failure -> {
val e = it.error
if (e is CloudFlareProtectedException) {
CaptchaNotifier(applicationContext).notify(e)
}
}
is MangaUpdates.Success -> {
if (it.isValid && it.isNotEmpty()) {
showNotification(
manga = it.manga,
channelId = it.channelId,
newChapters = it.newChapters,
)
}
}
}
}.toList(ArrayList(tracks.size)) }.toList(ArrayList(tracks.size))
} }
private suspend fun showNotification(manga: Manga, channelId: String?, newChapters: List<MangaChapter>) { private suspend fun showNotification(
manga: Manga,
channelId: String?,
newChapters: List<MangaChapter>,
) {
if (newChapters.isEmpty() || channelId == null || !applicationContext.checkNotificationPermission()) { if (newChapters.isEmpty() || channelId == null || !applicationContext.checkNotificationPermission()) {
return return
} }
@ -239,7 +253,10 @@ class TrackWorker @AssistedInject constructor(
override suspend fun getForegroundInfo(): ForegroundInfo { override suspend fun getForegroundInfo(): ForegroundInfo {
val title = applicationContext.getString(R.string.check_for_new_chapters) val title = applicationContext.getString(R.string.check_for_new_chapters)
val channel = NotificationChannelCompat.Builder(WORKER_CHANNEL_ID, NotificationManagerCompat.IMPORTANCE_LOW) val channel = NotificationChannelCompat.Builder(
WORKER_CHANNEL_ID,
NotificationManagerCompat.IMPORTANCE_LOW
)
.setName(title) .setName(title)
.setShowBadge(false) .setShowBadge(false)
.setVibrationEnabled(false) .setVibrationEnabled(false)
@ -260,7 +277,11 @@ class TrackWorker @AssistedInject constructor(
.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_DEFERRED) .setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_DEFERRED)
.build() .build()
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ForegroundInfo(WORKER_NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC) ForegroundInfo(
WORKER_NOTIFICATION_ID,
notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
)
} else { } else {
ForegroundInfo(WORKER_NOTIFICATION_ID, notification) ForegroundInfo(WORKER_NOTIFICATION_ID, notification)
} }
@ -320,7 +341,8 @@ class TrackWorker @AssistedInject constructor(
} }
fun startNow() { fun startNow() {
val constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build() val constraints =
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
val request = OneTimeWorkRequestBuilder<TrackWorker>() val request = OneTimeWorkRequestBuilder<TrackWorker>()
.setConstraints(constraints) .setConstraints(constraints)
.addTag(TAG_ONESHOT) .addTag(TAG_ONESHOT)

Loading…
Cancel
Save