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 { kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString() jvmTarget = JavaVersion.VERSION_1_8.toString()
freeCompilerArgs += [ freeCompilerArgs += [
'-opt-in=kotlin.ExperimentalStdlibApi',
'-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi', '-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi',
'-opt-in=kotlinx.coroutines.FlowPreview', '-opt-in=kotlinx.coroutines.FlowPreview',
'-opt-in=kotlin.contracts.ExperimentalContracts', '-opt-in=kotlin.contracts.ExperimentalContracts',

View File

@@ -2,15 +2,4 @@ package org.koitharu.kotatsu.core.cache
import androidx.collection.LruCache import androidx.collection.LruCache
class DeferredLruCache<T>(maxSize: Int) : LruCache<ContentCache.Key, SafeDeferred<T>>(maxSize) { 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()
}
}

View File

@@ -1,8 +1,11 @@
package org.koitharu.kotatsu.core.parser package org.koitharu.kotatsu.core.parser
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainCoroutineDispatcher
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.currentCoroutineContext
import org.koitharu.kotatsu.core.cache.ContentCache import org.koitharu.kotatsu.core.cache.ContentCache
import org.koitharu.kotatsu.core.cache.SafeDeferred import org.koitharu.kotatsu.core.cache.SafeDeferred
import org.koitharu.kotatsu.core.prefs.SourceSettings import org.koitharu.kotatsu.core.prefs.SourceSettings
@@ -76,9 +79,15 @@ class RemoteMangaRepository(
private fun getConfig() = parser.config as SourceSettings private fun getConfig() = parser.config as SourceSettings
private fun <T> asyncSafe(block: suspend CoroutineScope.() -> T) = SafeDeferred( private suspend fun <T> asyncSafe(block: suspend CoroutineScope.() -> T): SafeDeferred<T> {
processLifecycleScope.async(Dispatchers.Default) { var dispatcher = currentCoroutineContext()[CoroutineDispatcher.Key]
runCatchingCancellable { block() } 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 android.content.Intent
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.EntryPointAccessors import dagger.hilt.android.EntryPointAccessors
import kotlinx.coroutines.coroutineScope
import org.koitharu.kotatsu.base.ui.CoroutineIntentService import org.koitharu.kotatsu.base.ui.CoroutineIntentService
import org.koitharu.kotatsu.core.cache.ContentCache import org.koitharu.kotatsu.core.cache.ContentCache
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
@@ -47,7 +46,7 @@ class MangaPrefetchService : CoroutineIntentService() {
override fun onError(startId: Int, error: Throwable) = Unit 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) val source = mangaRepositoryFactory.create(manga.source)
runCatchingCancellable { source.getDetails(manga) } runCatchingCancellable { source.getDetails(manga) }
} }

View File

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