diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/DownloadManager.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/DownloadManager.kt index 561bfeeb..ca5d885f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/DownloadManager.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/DownloadManager.kt @@ -20,7 +20,9 @@ import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.sample import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch @@ -70,6 +72,10 @@ object DownloadManager { .apply() } + private fun triggerSaveDownloadQueue() { + scope.launch { saveQueueFlow.emit(Unit) } + } + fun restoreAndResumeDownloads() { scope.launch { logger.debug { "restoreAndResumeDownloads: Restore download queue..." } @@ -126,6 +132,11 @@ object DownloadManager { } } + private val saveQueueFlow = MutableSharedFlow(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) + init { + saveQueueFlow.onEach { saveDownloadQueue() }.launchIn(scope) + } + private fun sendStatusToAllClients() { val status = getStatus() clients.forEach { @@ -186,7 +197,6 @@ object DownloadManager { private fun refreshDownloaders() { scope.launch { downloaderWatch.emit(Unit) - saveDownloadQueue() } } @@ -196,7 +206,8 @@ object DownloadManager { sourceId = sourceId, downloadQueue = downloadQueue, notifier = ::notifyAllClients, - onComplete = ::refreshDownloaders + onComplete = ::refreshDownloaders, + onDownloadFinished = ::triggerSaveDownloadQueue ) } @@ -276,7 +287,7 @@ object DownloadManager { manga ) downloadQueue.add(newDownloadChapter) - saveDownloadQueue() + triggerSaveDownloadQueue() logger.debug { "Added chapter ${chapter.id} to download queue ($newDownloadChapter)" } return newDownloadChapter } @@ -308,30 +319,33 @@ object DownloadManager { logger.debug { "dequeue ${chapterDownloads.size} chapters [${chapterDownloads.joinToString(separator = ", ") { "$it" }}]" } downloadQueue.removeAll(chapterDownloads) - saveDownloadQueue() + triggerSaveDownloadQueue() notifyAllClients() } fun reorder(chapterIndex: Int, mangaId: Int, to: Int) { - require(to >= 0) { "'to' must be over or equal to 0" } val download = downloadQueue.find { it.mangaId == mangaId && it.chapterIndex == chapterIndex } ?: return + reorder(download, to) + } + + fun reorder(chapterId: Int, to: Int) { + val download = downloadQueue.find { it.chapter.id == chapterId } + ?: return + + reorder(download, to) + } + + private fun reorder(download: DownloadChapter, to: Int) { + require(to >= 0) { "'to' must be over or equal to 0" } + logger.debug { "reorder download $download from ${downloadQueue.indexOf(download)} to $to" } downloadQueue -= download downloadQueue.add(to, download) - saveDownloadQueue() - } - - fun reorder(chapterId: Int, to: Int) { - require(to >= 0) { "'to' must be over or equal to 0" } - val download = downloadQueue.find { it.chapter.id == chapterId } - ?: return - downloadQueue -= download - downloadQueue.add(to, download) - saveDownloadQueue() + triggerSaveDownloadQueue() } fun start() { @@ -360,7 +374,7 @@ object DownloadManager { stop() downloadQueue.clear() - saveDownloadQueue() + triggerSaveDownloadQueue() notifyAllClients() } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/Downloader.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/Downloader.kt index e00ac578..bc080fb8 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/Downloader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/Downloader.kt @@ -34,7 +34,8 @@ class Downloader( val sourceId: String, private val downloadQueue: CopyOnWriteArrayList, private val notifier: (immediate: Boolean) -> Unit, - private val onComplete: () -> Unit + private val onComplete: () -> Unit, + private val onDownloadFinished: () -> Unit ) { private val logger = KotlinLogging.logger("${Downloader::class.java.name} source($sourceId)") @@ -112,6 +113,7 @@ class Downloader( downloadQueue.removeIf { it.mangaId == download.mangaId && it.chapterIndex == download.chapterIndex } step(null, false) downloadLogger.debug { "finished" } + onDownloadFinished() } catch (e: CancellationException) { logger.debug("Downloader was stopped") availableSourceDownloads.filter { it.state == Downloading }.forEach { it.state = Queued }