Fix tracker cancellation errors

This commit is contained in:
Koitharu
2023-01-20 14:28:59 +02:00
parent c09dd92cff
commit 2fbfd14252
5 changed files with 22 additions and 27 deletions

View File

@@ -56,6 +56,7 @@ android {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
freeCompilerArgs += [
'-opt-in=kotlin.ExperimentalStdlibApi',
'-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi',
'-opt-in=kotlinx.coroutines.FlowPreview',
'-opt-in=kotlin.contracts.ExperimentalContracts',

View File

@@ -2,15 +2,4 @@ package org.koitharu.kotatsu.core.cache
import androidx.collection.LruCache
class DeferredLruCache<T>(maxSize: Int) : LruCache<ContentCache.Key, SafeDeferred<T>>(maxSize) {
override fun entryRemoved(
evicted: Boolean,
key: ContentCache.Key,
oldValue: SafeDeferred<T>,
newValue: SafeDeferred<T>?,
) {
super.entryRemoved(evicted, key, oldValue, newValue)
oldValue.cancel()
}
}
class DeferredLruCache<T>(maxSize: Int) : LruCache<ContentCache.Key, SafeDeferred<T>>(maxSize)

View File

@@ -1,8 +1,11 @@
package org.koitharu.kotatsu.core.parser
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainCoroutineDispatcher
import kotlinx.coroutines.async
import kotlinx.coroutines.currentCoroutineContext
import org.koitharu.kotatsu.core.cache.ContentCache
import org.koitharu.kotatsu.core.cache.SafeDeferred
import org.koitharu.kotatsu.core.prefs.SourceSettings
@@ -76,9 +79,15 @@ class RemoteMangaRepository(
private fun getConfig() = parser.config as SourceSettings
private fun <T> asyncSafe(block: suspend CoroutineScope.() -> T) = SafeDeferred(
processLifecycleScope.async(Dispatchers.Default) {
runCatchingCancellable { block() }
},
)
private suspend fun <T> asyncSafe(block: suspend CoroutineScope.() -> T): SafeDeferred<T> {
var dispatcher = currentCoroutineContext()[CoroutineDispatcher.Key]
if (dispatcher == null || dispatcher is MainCoroutineDispatcher) {
dispatcher = Dispatchers.Default
}
return SafeDeferred(
processLifecycleScope.async(dispatcher) {
runCatchingCancellable { block() }
},
)
}
}

View File

@@ -4,7 +4,6 @@ import android.content.Context
import android.content.Intent
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.EntryPointAccessors
import kotlinx.coroutines.coroutineScope
import org.koitharu.kotatsu.base.ui.CoroutineIntentService
import org.koitharu.kotatsu.core.cache.ContentCache
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
@@ -47,7 +46,7 @@ class MangaPrefetchService : CoroutineIntentService() {
override fun onError(startId: Int, error: Throwable) = Unit
private suspend fun prefetchDetails(manga: Manga) = coroutineScope {
private suspend fun prefetchDetails(manga: Manga) {
val source = mangaRepositoryFactory.create(manga.source)
runCatchingCancellable { source.getDetails(manga) }
}

View File

@@ -30,12 +30,11 @@ import coil.ImageLoader
import coil.request.ImageRequest
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.withContext
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.logs.FileLogger
@@ -94,8 +93,7 @@ class TrackWorker @AssistedInject constructor(
return Result.success(workDataOf(0, 0))
}
val updates = checkUpdatesAsync(tracks)
val results = updates.awaitAll()
val results = checkUpdatesAsync(tracks)
tracker.gc()
var success = 0
@@ -116,9 +114,9 @@ class TrackWorker @AssistedInject constructor(
}
}
private suspend fun checkUpdatesAsync(tracks: List<TrackingItem>): List<Deferred<MangaUpdates?>> {
private suspend fun checkUpdatesAsync(tracks: List<TrackingItem>): List<MangaUpdates?> {
val dispatcher = Dispatchers.Default.limitedParallelism(MAX_PARALLELISM)
val deferredList = coroutineScope {
return supervisorScope {
tracks.map { (track, channelId) ->
async(dispatcher) {
runCatchingCancellable {
@@ -135,9 +133,8 @@ class TrackWorker @AssistedInject constructor(
}
}.getOrNull()
}
}
}.awaitAll()
}
return deferredList
}
private suspend fun showNotification(manga: Manga, channelId: String?, newChapters: List<MangaChapter>) {