added async management for book parsing

This commit is contained in:
Gauthier Roebroeck 2019-08-20 18:19:23 +08:00
parent 1c298221f8
commit cb867ff519
4 changed files with 39 additions and 8 deletions

View file

@ -6,8 +6,11 @@ import org.gotson.komga.domain.model.Book
import org.gotson.komga.domain.model.BookMetadata
import org.gotson.komga.domain.model.Status
import org.gotson.komga.domain.persistence.BookRepository
import org.springframework.scheduling.annotation.Async
import org.springframework.scheduling.annotation.AsyncResult
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.util.concurrent.Future
import kotlin.system.measureTimeMillis
private val logger = KotlinLogging.logger {}
@ -19,9 +22,10 @@ class BookManager(
) {
@Transactional
fun parseAndPersist(book: Book) {
@Async("parseBookTaskExecutor")
fun parseAndPersist(book: Book): Future<Long> {
logger.info { "Parse and persist book: ${book.url}" }
measureTimeMillis {
return AsyncResult(measureTimeMillis {
try {
book.metadata = bookParser.parse(book)
} catch (ex: UnsupportedMediaTypeException) {
@ -32,7 +36,7 @@ class BookManager(
book.metadata = BookMetadata(status = Status.ERROR)
}
bookRepository.save(book)
}.also { logger.info { "Parsing finished in ${DurationFormatUtils.formatDurationHMS(it)}" } }
}.also { logger.info { "Parsing finished in ${DurationFormatUtils.formatDurationHMS(it)}" } })
}
}

View file

@ -80,10 +80,17 @@ class LibraryManager(
}
fun parseUnparsedBooks() {
logger.info { "Parsing all books in status: unkown" }
logger.info { "Parsing all books in status: unknown" }
val booksToParse = bookRepository.findAllByMetadataStatus(Status.UNKNOWN)
var sumOfTasksTime = 0L
measureTimeMillis {
booksToParse.forEach { bookManager.parseAndPersist(it) }
}.also { logger.info { "Parsed ${booksToParse.size} books in ${DurationFormatUtils.formatDurationHMS(it)}" } }
sumOfTasksTime = booksToParse
.map { bookManager.parseAndPersist(it) }
.map { it.get() }
.sum()
}.also {
logger.info { "Parsed ${booksToParse.size} books in ${DurationFormatUtils.formatDurationHMS(it)} (virtual: ${DurationFormatUtils.formatDurationHMS(sumOfTasksTime)})" }
}
}
}

View file

@ -0,0 +1,18 @@
package org.gotson.komga.infrastructure.async
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.scheduling.annotation.EnableAsync
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
import java.util.concurrent.Executor
@Configuration
@EnableAsync
class AsyncConfiguration {
@Bean
fun parseBookTaskExecutor(): Executor =
ThreadPoolTaskExecutor().apply {
corePoolSize = 5
}
}

View file

@ -25,7 +25,6 @@ import javax.persistence.EntityManager
@ExtendWith(SpringExtension::class)
@SpringBootTest
@AutoConfigureTestDatabase
@Transactional
class LibraryManagerTest(
@Autowired private val serieRepository: SerieRepository,
@Autowired private val bookRepository: BookRepository,
@ -48,6 +47,7 @@ class LibraryManagerTest(
}
@Test
@Transactional
fun `given existing Serie when adding files and scanning then only updated Books are persisted`() {
//given
val serie = makeSerie(name = "serie", books = listOf(makeBook("book1")))
@ -73,6 +73,7 @@ class LibraryManagerTest(
}
@Test
@Transactional
fun `given existing Serie when removing files and scanning then only updated Books are persisted`() {
//given
val serie = makeSerie(name = "serie", books = listOf(makeBook("book1"), makeBook("book2")))
@ -100,6 +101,7 @@ class LibraryManagerTest(
}
@Test
@Transactional
fun `given existing Serie when updating files and scanning then Books are updated`() {
//given
val serie = makeSerie(name = "serie", books = listOf(makeBook("book1")))
@ -161,7 +163,7 @@ class LibraryManagerTest(
libraryManager.scanRootFolder(library)
every { mockParser.parse(any()) } returns BookMetadata(status = Status.READY, mediaType = "application/zip", pages = mutableListOf(makeBookPage("1.jpg"), makeBookPage("2.jpg")))
bookRepository.findAll().forEach { bookManager.parseAndPersist(it) }
bookRepository.findAll().map { bookManager.parseAndPersist(it) }.map { it.get() }
// when
libraryManager.scanRootFolder(library)