feat: automatic database backup

closes #138
This commit is contained in:
Gauthier Roebroeck 2020-06-08 17:00:34 +08:00
parent 425756557a
commit bbb9f7ce06
9 changed files with 91 additions and 2 deletions

View file

@ -4,6 +4,7 @@ ARG DEPENDENCY=build/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY ${DEPENDENCY}/META-INF /app/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes /app
ENV KOMGA_DATABASE_BACKUP_PATH="/config/database-backup.zip"
ENV SPRING_DATASOURCE_URL="jdbc:h2:/config/database.h2"
ENV SPRING_ARTEMIS_EMBEDDED_DATA_DIRECTORY="/config/artemis"
ENV LOGGING_FILE_NAME="/config/logs/komga.log"

View file

@ -20,4 +20,9 @@ sealed class Task : Serializable {
data class RefreshBookMetadata(val bookId: Long) : Task() {
override fun uniqueId() = "REFRESH_BOOK_METADATA_$bookId"
}
object BackupDatabase : Task() {
override fun uniqueId(): String = "BACKUP_DATABASE"
override fun toString(): String = "BackupDatabase"
}
}

View file

@ -6,6 +6,7 @@ import org.gotson.komga.domain.persistence.LibraryRepository
import org.gotson.komga.domain.service.BookLifecycle
import org.gotson.komga.domain.service.LibraryScanner
import org.gotson.komga.domain.service.MetadataLifecycle
import org.gotson.komga.infrastructure.h2.DatabaseBackuper
import org.gotson.komga.infrastructure.jms.QUEUE_TASKS
import org.gotson.komga.infrastructure.jms.QUEUE_TASKS_SELECTOR
import org.springframework.jms.annotation.JmsListener
@ -21,7 +22,8 @@ class TaskHandler(
private val bookRepository: BookRepository,
private val libraryScanner: LibraryScanner,
private val bookLifecycle: BookLifecycle,
private val metadataLifecycle: MetadataLifecycle
private val metadataLifecycle: MetadataLifecycle,
private val databaseBackuper: DatabaseBackuper
) {
@JmsListener(destination = QUEUE_TASKS, selector = QUEUE_TASKS_SELECTOR)
@ -53,6 +55,10 @@ class TaskHandler(
metadataLifecycle.refreshMetadata(it)
} ?: logger.warn { "Cannot execute task $task: Book does not exist" }
is Task.BackupDatabase -> {
databaseBackuper.backupDatabase()
}
}
}.also {
logger.info { "Task $task executed in $it" }

View file

@ -60,6 +60,10 @@ class TaskReceiver(
submitTask(Task.RefreshBookMetadata(book.id))
}
fun databaseBackup() {
submitTask(Task.BackupDatabase)
}
private fun submitTask(task: Task) {
logger.info { "Sending task: $task" }
jmsTemplate.convertAndSend(QUEUE_TASKS, task) {

View file

@ -27,4 +27,13 @@ class KomgaProperties {
@Positive
var validity: Int = 1209600 // 2 weeks
}
var databaseBackup = DatabaseBackup()
class DatabaseBackup {
var enabled: Boolean = true
var path: String = ""
var schedule: String = ""
var startup: Boolean = true
}
}

View file

@ -0,0 +1,28 @@
package org.gotson.komga.infrastructure.h2
import mu.KotlinLogging
import org.gotson.komga.infrastructure.configuration.KomgaProperties
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.stereotype.Component
import java.nio.file.Files
import java.nio.file.Paths
private val logger = KotlinLogging.logger {}
@Component
class DatabaseBackuper(
private val jdbcTemplate: JdbcTemplate,
private val komgaProperties: KomgaProperties
) {
fun backupDatabase() {
val path = Paths.get(komgaProperties.databaseBackup.path)
Files.deleteIfExists(path)
val command = "BACKUP TO '$path'"
logger.info { "Executing command: $command" }
jdbcTemplate.execute(command)
}
}

View file

@ -0,0 +1,29 @@
package org.gotson.komga.interfaces.scheduler
import mu.KotlinLogging
import org.gotson.komga.application.tasks.TaskReceiver
import org.gotson.komga.infrastructure.configuration.KomgaProperties
import org.springframework.boot.context.event.ApplicationReadyEvent
import org.springframework.context.annotation.Profile
import org.springframework.context.event.EventListener
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Controller
private val logger = KotlinLogging.logger {}
@Profile("!test")
@Controller
class PeriodicDatabaseBackupController(
private val taskReceiver: TaskReceiver,
private val komgaProperties: KomgaProperties
) {
@EventListener(classes = [ApplicationReadyEvent::class], condition = "@komgaProperties.databaseBackup.startup")
@Scheduled(cron = "#{@komgaProperties.databaseBackup.schedule ?: '-'}")
fun scanAllLibraries() {
if (komgaProperties.databaseBackup.enabled) {
logger.info { "Periodic database backup" }
taskReceiver.databaseBackup()
}
}
}

View file

@ -3,9 +3,13 @@ komga:
remember-me:
key: changeMe!
validity: 2592000 # 1 month
# libraries-scan-cron: "*/5 * * * * ?" #every 5 seconds
# libraries-scan-cron: "*/5 * * * * ?" #every 5 seconds
libraries-scan-cron: "-" #disable
libraries-scan-startup: true
database-backup:
enabled: false
path: ./backup.zip
schedule: "*/15 * * * * ?"
spring:
datasource:
url: jdbc:h2:mem:testdb

View file

@ -12,6 +12,9 @@ komga:
libraries-scan-directory-exclusions:
- "#recycle"
- "@eaDir"
database-backup:
path: ~/.komga/database-backup.zip
schedule: "0 0 */6 * * ?"
spring:
# cache: