Fix/downloader manager persisting queue (#639)
* Extract reorder logic into function * Save download queue everytime a download was finished The download queue was never saved after a download was finished. This caused finished download to be restored on a server start, which caused unnecessary "downloads" which most of the time would just finish immediately since the pages were still in the cache * Wait for download queue save process to be finished Since multiple downloaders could be finished at the same time, the download queue should be saved synchronously * Remove unnecessary download queue save trigger This gets called everytime a downloader finished downloading all chapters of its source. Since the queue is now saved everytime a download is finished, this is trigger is not needed anymore
This commit is contained in:
@@ -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<Unit>(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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@ class Downloader(
|
||||
val sourceId: String,
|
||||
private val downloadQueue: CopyOnWriteArrayList<DownloadChapter>,
|
||||
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 }
|
||||
|
||||
Reference in New Issue
Block a user