mirror of
https://github.com/Suwayomi/Tachidesk.git
synced 2025-12-10 06:42:07 +01:00
Fix/gql download subscription errors spamming emits (#1518)
* Remove immediate download notification for latest gql subscription There is a problem where too many immediate updates can cause the client to lag out (e.g., in case it has to update the queue in the cache based on the updates). This happens in case e.g., a source is broken and all its downloads error out basically immediately. With each errored out download, a new one starts, which causes an immediate notification to the clients. * Determine downloader status from active state of downloader jobs In case the downloader is active but all downloads are erroring out immediately, no download will have the DOWNLOADING status. This then would result in the downloader status to constantly be STOPPED. * Prevent multiple update for the same downloads It was possible that multiple updates got added for the same download. This caused issues with the graphql apollo client, because it wasn't able to correctly update the client cache. * Set download error state only after reaching max retries In case the max retries haven't been reached yet, the download will be retried and thus setting and emitting the error state will cause weird looking ui updates.
This commit is contained in:
@@ -31,7 +31,6 @@ import org.jetbrains.exposed.sql.and
|
||||
import org.jetbrains.exposed.sql.selectAll
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter
|
||||
import suwayomi.tachidesk.manga.impl.download.model.DownloadState.Downloading
|
||||
import suwayomi.tachidesk.manga.impl.download.model.DownloadState.Error
|
||||
import suwayomi.tachidesk.manga.impl.download.model.DownloadState.Queued
|
||||
import suwayomi.tachidesk.manga.impl.download.model.DownloadStatus
|
||||
@@ -147,7 +146,7 @@ object DownloadManager {
|
||||
init {
|
||||
scope.launch {
|
||||
notifyFlow.sample(1.seconds).collect {
|
||||
notifyAllClients(immediate = true)
|
||||
notifyAllClients(immediate = true, gqlEmit = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,18 +166,37 @@ object DownloadManager {
|
||||
private fun notifyAllClients(
|
||||
immediate: Boolean = false,
|
||||
downloads: List<DownloadUpdate> = emptyList(),
|
||||
gqlEmit: Boolean = false,
|
||||
) {
|
||||
downloadUpdates.removeAll { update ->
|
||||
downloads.any { download ->
|
||||
download.downloadChapter.chapter.id ==
|
||||
update.downloadChapter.chapter.id
|
||||
}
|
||||
}
|
||||
downloadUpdates.addAll(downloads)
|
||||
|
||||
if (immediate) {
|
||||
val status = getStatus()
|
||||
// There is a problem where too many immediate updates can cause the client to lag out (e.g., in case it has to
|
||||
// update the queue in the cache based on the updates).
|
||||
// This happens in case e.g., a source is broken and all its downloads error out basically immediately.
|
||||
// With each errored out download, a new one starts, which causes an immediate notification to the clients.
|
||||
// While the immediate notification functionality is no longer needed for the latest graphql download subscription,
|
||||
// it is still required for the deprecated version as well as the rest api subscription.
|
||||
if (gqlEmit) {
|
||||
val updates = getDownloadUpdates()
|
||||
|
||||
downloadUpdates.clear()
|
||||
|
||||
scope.launch {
|
||||
statusFlow.emit(status)
|
||||
updatesFlow.emit(updates)
|
||||
}
|
||||
}
|
||||
|
||||
if (immediate) {
|
||||
val status = getStatus()
|
||||
|
||||
scope.launch {
|
||||
statusFlow.emit(status)
|
||||
sendStatusToAllClients(status)
|
||||
}
|
||||
|
||||
@@ -192,20 +210,20 @@ object DownloadManager {
|
||||
|
||||
fun getStatus(): DownloadStatus =
|
||||
DownloadStatus(
|
||||
if (downloadQueue.none { it.state == Downloading }) {
|
||||
Status.Stopped
|
||||
} else {
|
||||
if (downloaders.values.any { it.isActive }) {
|
||||
Status.Started
|
||||
} else {
|
||||
Status.Stopped
|
||||
},
|
||||
downloadQueue.toList(),
|
||||
)
|
||||
|
||||
private fun getDownloadUpdates(addInitial: Boolean = false): DownloadUpdates =
|
||||
DownloadUpdates(
|
||||
if (downloadQueue.none { it.state == Downloading }) {
|
||||
Status.Stopped
|
||||
} else {
|
||||
if (downloaders.values.any { it.isActive }) {
|
||||
Status.Started
|
||||
} else {
|
||||
Status.Stopped
|
||||
},
|
||||
downloadUpdates.toList(),
|
||||
if (addInitial) downloadQueue.toList() else null,
|
||||
|
||||
@@ -171,8 +171,11 @@ class Downloader(
|
||||
} catch (e: Exception) {
|
||||
downloadLogger.warn(e) { "failed due to" }
|
||||
download.tries++
|
||||
download.state = Error
|
||||
notifier(false, DownloadUpdate(ERROR, download))
|
||||
download.state = Queued
|
||||
if (download.tries >= MAX_RETRIES) {
|
||||
download.state = Error
|
||||
notifier(false, DownloadUpdate(ERROR, download))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user