Fix coroutines cancellation

This commit is contained in:
Koitharu
2022-09-21 18:35:38 +03:00
parent 73478d6a81
commit 1e75edf262
33 changed files with 217 additions and 130 deletions

View File

@@ -21,6 +21,7 @@ import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.parsers.util.levenshteinDistance
import org.koitharu.kotatsu.search.ui.MangaSuggestionsProvider
import org.koitharu.kotatsu.utils.ext.runCatchingCancellable
class MangaSearchRepository @Inject constructor(
private val settings: AppSettings,
@@ -33,7 +34,7 @@ class MangaSearchRepository @Inject constructor(
fun globalSearch(query: String, concurrency: Int = DEFAULT_CONCURRENCY): Flow<Manga> =
settings.getMangaSources(includeHidden = false).asFlow()
.flatMapMerge(concurrency) { source ->
runCatching {
runCatchingCancellable {
mangaRepositoryFactory.create(source).getList(
offset = 0,
query = query,

View File

@@ -4,6 +4,7 @@ import androidx.lifecycle.viewModelScope
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
@@ -12,7 +13,13 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.list.ui.MangaListViewModel
import org.koitharu.kotatsu.list.ui.model.*
import org.koitharu.kotatsu.list.ui.model.EmptyState
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.list.ui.model.LoadingFooter
import org.koitharu.kotatsu.list.ui.model.LoadingState
import org.koitharu.kotatsu.list.ui.model.toErrorFooter
import org.koitharu.kotatsu.list.ui.model.toErrorState
import org.koitharu.kotatsu.list.ui.model.toUi
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
@@ -47,6 +54,7 @@ class SearchViewModel @AssistedInject constructor(
actionStringRes = 0,
),
)
else -> {
val result = ArrayList<ListModel>(list.size + 1)
list.toUi(result, mode)
@@ -94,6 +102,8 @@ class SearchViewModel @AssistedInject constructor(
mangaList.value = mangaList.value?.plus(list) ?: list
}
hasNextPage.value = list.isNotEmpty()
} catch (e: CancellationException) {
throw e
} catch (e: Throwable) {
listError.value = e
}

View File

@@ -20,6 +20,7 @@ import org.koitharu.kotatsu.list.ui.model.*
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
import org.koitharu.kotatsu.utils.ext.printStackTraceDebug
import org.koitharu.kotatsu.utils.ext.runCatchingCancellable
private const val MAX_PARALLELISM = 4
private const val MIN_HAS_MORE_ITEMS = 8
@@ -54,6 +55,7 @@ class MultiSearchViewModel @AssistedInject constructor(
)
},
)
loading -> list + LoadingFooter
else -> list
}
@@ -85,6 +87,8 @@ class MultiSearchViewModel @AssistedInject constructor(
loadingData.value = true
query.postValue(q)
searchImpl(q)
} catch (e: CancellationException) {
throw e
} catch (e: Throwable) {
listError.value = e
} finally {
@@ -98,7 +102,7 @@ class MultiSearchViewModel @AssistedInject constructor(
val dispatcher = Dispatchers.Default.limitedParallelism(MAX_PARALLELISM)
val deferredList = sources.map { source ->
async(dispatcher) {
runCatching {
runCatchingCancellable {
val list = mangaRepositoryFactory.create(source).getList(offset = 0, query = q)
.toUi(ListMode.GRID)
if (list.isNotEmpty()) {