Fix tracker cancellation errors
This commit is contained in:
@@ -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',
|
||||||
|
|||||||
@@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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() }
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>) {
|
||||||
|
|||||||
Reference in New Issue
Block a user