mirror of
https://github.com/gotson/komga.git
synced 2025-12-25 01:42:44 +01:00
feat(api): configure number of task processing threads
This commit is contained in:
parent
528eddb94c
commit
9ef319b703
7 changed files with 37 additions and 3 deletions
|
|
@ -1,3 +1,4 @@
|
|||
package org.gotson.komga.application.tasks
|
||||
|
||||
class TaskAddedEvent
|
||||
class TaskPoolSizeChangedEvent
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package org.gotson.komga.application.tasks
|
||||
|
||||
import mu.KotlinLogging
|
||||
import org.gotson.komga.infrastructure.configuration.KomgaSettingsProvider
|
||||
import org.springframework.beans.factory.InitializingBean
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent
|
||||
import org.springframework.boot.task.TaskExecutorBuilder
|
||||
|
|
@ -14,12 +15,13 @@ private val logger = KotlinLogging.logger {}
|
|||
class TaskProcessor(
|
||||
private val tasksRepository: TasksRepository,
|
||||
private val taskHandler: TaskHandler,
|
||||
private val settingsProvider: KomgaSettingsProvider,
|
||||
taskExecutorBuilder: TaskExecutorBuilder,
|
||||
) : InitializingBean {
|
||||
val executor: ThreadPoolTaskExecutor =
|
||||
taskExecutorBuilder
|
||||
.threadNamePrefix("taskProcessor-")
|
||||
.corePoolSize(8)
|
||||
.corePoolSize(settingsProvider.taskPoolSize)
|
||||
.build()
|
||||
.apply { initialize() }
|
||||
|
||||
|
|
@ -32,11 +34,18 @@ class TaskProcessor(
|
|||
processTasks = true
|
||||
}
|
||||
|
||||
@EventListener(TaskPoolSizeChangedEvent::class)
|
||||
fun taskPoolSizeChanged() {
|
||||
executor.corePoolSize = settingsProvider.taskPoolSize
|
||||
}
|
||||
|
||||
@EventListener(TaskAddedEvent::class, ApplicationReadyEvent::class)
|
||||
fun processAvailableTask() {
|
||||
if (processTasks) {
|
||||
logger.debug { "Active count: ${executor.activeCount}, Core Pool Size: ${executor.corePoolSize}, Pool Size: ${executor.poolSize}" }
|
||||
if (executor.corePoolSize == 1) executor.execute { takeAndProcess() }
|
||||
// fan out while threads are available
|
||||
while (tasksRepository.hasAvailable() && executor.activeCount < executor.corePoolSize)
|
||||
else while (tasksRepository.hasAvailable() && executor.activeCount < executor.corePoolSize)
|
||||
executor.execute { takeAndProcess() }
|
||||
} else {
|
||||
logger.debug { "Not processing tasks" }
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
package org.gotson.komga.infrastructure.configuration
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils
|
||||
import org.gotson.komga.application.tasks.TaskPoolSizeChangedEvent
|
||||
import org.gotson.komga.domain.model.ThumbnailSize
|
||||
import org.gotson.komga.infrastructure.jooq.main.ServerSettingsDao
|
||||
import org.springframework.context.ApplicationEventPublisher
|
||||
import org.springframework.stereotype.Service
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.days
|
||||
|
|
@ -10,6 +12,7 @@ import kotlin.time.Duration.Companion.days
|
|||
@Service
|
||||
class KomgaSettingsProvider(
|
||||
private val serverSettingsDao: ServerSettingsDao,
|
||||
private val eventPublisher: ApplicationEventPublisher,
|
||||
) {
|
||||
var deleteEmptyCollections: Boolean =
|
||||
serverSettingsDao.getSettingByKey(Settings.DELETE_EMPTY_COLLECTIONS.name, Boolean::class.java) ?: false
|
||||
|
|
@ -54,6 +57,14 @@ class KomgaSettingsProvider(
|
|||
serverSettingsDao.saveSetting(Settings.THUMBNAIL_SIZE.name, value.name)
|
||||
field = value
|
||||
}
|
||||
|
||||
var taskPoolSize: Int =
|
||||
serverSettingsDao.getSettingByKey(Settings.TASK_POOL_SIZE.name, Int::class.java) ?: 8
|
||||
set(value) {
|
||||
serverSettingsDao.saveSetting(Settings.TASK_POOL_SIZE.name, value)
|
||||
field = value
|
||||
eventPublisher.publishEvent(TaskPoolSizeChangedEvent())
|
||||
}
|
||||
}
|
||||
|
||||
private enum class Settings {
|
||||
|
|
@ -62,4 +73,5 @@ private enum class Settings {
|
|||
REMEMBER_ME_KEY,
|
||||
REMEMBER_ME_DURATION,
|
||||
THUMBNAIL_SIZE,
|
||||
TASK_POOL_SIZE,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ class SettingsController(
|
|||
komgaSettingsProvider.deleteEmptyReadLists,
|
||||
komgaSettingsProvider.rememberMeDuration.inWholeDays,
|
||||
komgaSettingsProvider.thumbnailSize.toDto(),
|
||||
komgaSettingsProvider.taskPoolSize,
|
||||
)
|
||||
|
||||
@PatchMapping
|
||||
|
|
@ -45,5 +46,6 @@ class SettingsController(
|
|||
newSettings.rememberMeDurationDays?.let { komgaSettingsProvider.rememberMeDuration = it.days }
|
||||
if (newSettings.renewRememberMeKey == true) komgaSettingsProvider.renewRememberMeKey()
|
||||
newSettings.thumbnailSize?.let { komgaSettingsProvider.thumbnailSize = it.toDomain() }
|
||||
newSettings.taskPoolSize?.let { komgaSettingsProvider.taskPoolSize = it }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,4 +5,5 @@ data class SettingsDto(
|
|||
val deleteEmptyReadLists: Boolean,
|
||||
val rememberMeDurationDays: Long,
|
||||
val thumbnailSize: ThumbnailSizeDto,
|
||||
val taskPoolSize: Int,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,4 +9,6 @@ data class SettingsUpdateDto(
|
|||
val rememberMeDurationDays: Long? = null,
|
||||
val renewRememberMeKey: Boolean? = null,
|
||||
val thumbnailSize: ThumbnailSizeDto? = null,
|
||||
@get:Positive
|
||||
val taskPoolSize: Int? = null,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ class SettingsControllerTest(
|
|||
komgaSettingsProvider.deleteEmptyReadLists = false
|
||||
komgaSettingsProvider.rememberMeDuration = 5.days
|
||||
komgaSettingsProvider.thumbnailSize = ThumbnailSize.LARGE
|
||||
komgaSettingsProvider.taskPoolSize = 4
|
||||
|
||||
mockMvc.get("/api/v1/settings")
|
||||
.andExpect {
|
||||
|
|
@ -61,6 +62,7 @@ class SettingsControllerTest(
|
|||
jsonPath("deleteEmptyReadLists") { value(false) }
|
||||
jsonPath("rememberMeDurationDays") { value(5) }
|
||||
jsonPath("thumbnailSize") { value("LARGE") }
|
||||
jsonPath("taskPoolSize") { value(4) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -71,6 +73,7 @@ class SettingsControllerTest(
|
|||
komgaSettingsProvider.deleteEmptyReadLists = true
|
||||
komgaSettingsProvider.rememberMeDuration = 5.days
|
||||
komgaSettingsProvider.thumbnailSize = ThumbnailSize.LARGE
|
||||
komgaSettingsProvider.taskPoolSize = 4
|
||||
|
||||
val rememberMeKey = komgaSettingsProvider.rememberMeKey
|
||||
|
||||
|
|
@ -80,7 +83,8 @@ class SettingsControllerTest(
|
|||
"deleteEmptyCollections": false,
|
||||
"rememberMeDurationDays": 15,
|
||||
"renewRememberMeKey": true,
|
||||
"thumbnailSize": "MEDIUM"
|
||||
"thumbnailSize": "MEDIUM",
|
||||
"taskPoolSize": 8
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
|
|
@ -97,6 +101,7 @@ class SettingsControllerTest(
|
|||
assertThat(komgaSettingsProvider.rememberMeDuration).isEqualTo(15.days)
|
||||
assertThat(komgaSettingsProvider.rememberMeKey).isNotEqualTo(rememberMeKey)
|
||||
assertThat(komgaSettingsProvider.thumbnailSize).isEqualTo(ThumbnailSize.MEDIUM)
|
||||
assertThat(komgaSettingsProvider.taskPoolSize).isEqualTo(8)
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
|
|
@ -107,6 +112,8 @@ class SettingsControllerTest(
|
|||
"""{"rememberMeDurationDays": 0}""",
|
||||
//language=JSON
|
||||
"""{"thumbnailSize": "HUGE"}""",
|
||||
"""{"taskPoolSize": 0}""",
|
||||
"""{"taskPoolSize": -15}""",
|
||||
],
|
||||
)
|
||||
fun `given admin user when updating with invalid settings then returns bad request`(jsonString: String) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue