mirror of
https://github.com/GayPizzaSpecifications/foundation.git
synced 2025-08-02 13:10:55 +00:00
Initial work on scheduled backups.
This commit is contained in:
parent
b2851d13b9
commit
c1f621aa7b
@ -2,4 +2,5 @@ dependencies {
|
||||
// TODO: might be able to ship all dependencies in core? are we duplicating classes in JARs?
|
||||
|
||||
implementation("software.amazon.awssdk:s3:2.17.102")
|
||||
implementation("org.quartz-scheduler:quartz:2.3.2")
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import cloud.kubelet.foundation.core.features.stats.StatsFeature
|
||||
import cloud.kubelet.foundation.core.features.update.UpdateFeature
|
||||
import cloud.kubelet.foundation.core.features.world.WorldFeature
|
||||
import cloud.kubelet.foundation.core.features.persist.PersistenceFeature
|
||||
import cloud.kubelet.foundation.core.features.scheduler.SchedulerFeature
|
||||
import org.koin.dsl.module
|
||||
import java.nio.file.Path
|
||||
|
||||
@ -38,6 +39,7 @@ class FoundationCorePlugin : FoundationPlugin() {
|
||||
}
|
||||
|
||||
override fun createFeatures() = listOf(
|
||||
SchedulerFeature(),
|
||||
PersistenceFeature(),
|
||||
BackupFeature(),
|
||||
DevFeature(),
|
||||
|
@ -0,0 +1,7 @@
|
||||
package cloud.kubelet.foundation.core.abstraction
|
||||
|
||||
interface CoreFeature {
|
||||
fun enable()
|
||||
fun disable()
|
||||
fun module() = org.koin.dsl.module {}
|
||||
}
|
@ -7,13 +7,15 @@ import org.bukkit.event.Listener
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import org.koin.dsl.module
|
||||
import org.quartz.Scheduler
|
||||
|
||||
abstract class Feature : KoinComponent, Listener {
|
||||
abstract class Feature : CoreFeature, KoinComponent, Listener {
|
||||
private val plugin by inject<FoundationCorePlugin>()
|
||||
protected val scheduler by inject<Scheduler>()
|
||||
|
||||
open fun enable() {}
|
||||
open fun disable() {}
|
||||
open fun module() = module {}
|
||||
override fun enable() {}
|
||||
override fun disable() {}
|
||||
override fun module() = module {}
|
||||
|
||||
protected fun registerCommandExecutor(name: String, executor: CommandExecutor) {
|
||||
registerCommandExecutor(listOf(name), executor)
|
||||
|
@ -10,7 +10,7 @@ import org.koin.dsl.module
|
||||
abstract class FoundationPlugin : JavaPlugin() {
|
||||
private lateinit var pluginModule: Module
|
||||
private lateinit var pluginApplication: KoinApplication
|
||||
private lateinit var features: List<Feature>
|
||||
private lateinit var features: List<CoreFeature>
|
||||
private lateinit var module: Module
|
||||
|
||||
override fun onEnable() {
|
||||
@ -45,7 +45,10 @@ abstract class FoundationPlugin : JavaPlugin() {
|
||||
try {
|
||||
slF4JLogger.info("Enabling feature: ${it.javaClass.simpleName}")
|
||||
it.enable()
|
||||
server.pluginManager.registerEvents(it, this)
|
||||
// TODO: May replace this check with a method in the interface, CoreFeature would no-op.
|
||||
if (it is Feature) {
|
||||
server.pluginManager.registerEvents(it, this)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
slF4JLogger.error("Failed to enable feature: ${it.javaClass.simpleName}", e)
|
||||
}
|
||||
@ -61,5 +64,5 @@ abstract class FoundationPlugin : JavaPlugin() {
|
||||
}
|
||||
|
||||
protected open fun createModule() = module {}
|
||||
protected abstract fun createFeatures(): List<Feature>
|
||||
protected abstract fun createFeatures(): List<CoreFeature>
|
||||
}
|
||||
|
@ -4,9 +4,15 @@ import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class BackupConfig(
|
||||
val schedule: ScheduleConfig = ScheduleConfig(),
|
||||
val s3: S3Config = S3Config(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ScheduleConfig(
|
||||
val cron: String = "",
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class S3Config(
|
||||
val accessKeyId: String = "",
|
||||
|
@ -3,8 +3,9 @@ package cloud.kubelet.foundation.core.features.backup
|
||||
import cloud.kubelet.foundation.core.FoundationCorePlugin
|
||||
import cloud.kubelet.foundation.core.Util
|
||||
import cloud.kubelet.foundation.core.abstraction.Feature
|
||||
import cloud.kubelet.foundation.core.features.scheduler.cancel
|
||||
import cloud.kubelet.foundation.core.features.scheduler.cron
|
||||
import com.charleskorn.kaml.Yaml
|
||||
import org.koin.core.KoinApplication
|
||||
import org.koin.core.component.inject
|
||||
import org.koin.dsl.module
|
||||
import software.amazon.awssdk.auth.credentials.AwsSessionCredentials
|
||||
@ -18,6 +19,7 @@ class BackupFeature : Feature() {
|
||||
private val plugin by inject<FoundationCorePlugin>()
|
||||
private val s3Client by inject<S3Client>()
|
||||
private val config by inject<BackupConfig>()
|
||||
private lateinit var scheduleId: String
|
||||
|
||||
override fun enable() {
|
||||
// Create backup directory.
|
||||
@ -25,6 +27,20 @@ class BackupFeature : Feature() {
|
||||
backupPath.toFile().mkdir()
|
||||
|
||||
registerCommandExecutor("fbackup", BackupCommand(plugin, backupPath, config, s3Client))
|
||||
|
||||
if (config.schedule.cron.isNotEmpty()) {
|
||||
scheduleId = scheduler.cron("${config.schedule.cron} ?") {
|
||||
plugin.server.scheduler.runTask(plugin) { ->
|
||||
plugin.server.dispatchCommand(plugin.server.consoleSender, "fbackup")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun disable() {
|
||||
if (::scheduleId.isInitialized) {
|
||||
scheduler.cancel(scheduleId)
|
||||
}
|
||||
}
|
||||
|
||||
override fun module() = module {
|
||||
|
@ -0,0 +1,30 @@
|
||||
package cloud.kubelet.foundation.core.features.scheduler
|
||||
|
||||
import org.quartz.CronScheduleBuilder.cronSchedule
|
||||
import org.quartz.JobBuilder.newJob
|
||||
import org.quartz.JobDataMap
|
||||
import org.quartz.Scheduler
|
||||
import org.quartz.TriggerBuilder.newTrigger
|
||||
import org.quartz.TriggerKey.triggerKey
|
||||
import java.util.UUID
|
||||
|
||||
fun Scheduler.cron(cronExpression: String, f: () -> Unit): String {
|
||||
val id = UUID.randomUUID().toString()
|
||||
val job = newJob(SchedulerRunner::class.java).apply {
|
||||
setJobData(JobDataMap().apply {
|
||||
set("function", f)
|
||||
})
|
||||
}.build()
|
||||
|
||||
val trigger = newTrigger()
|
||||
.withIdentity(triggerKey(id))
|
||||
.withSchedule(cronSchedule(cronExpression))
|
||||
.build()
|
||||
|
||||
scheduleJob(job, trigger)
|
||||
return id
|
||||
}
|
||||
|
||||
fun Scheduler.cancel(id: String) {
|
||||
unscheduleJob(triggerKey(id))
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package cloud.kubelet.foundation.core.features.scheduler
|
||||
|
||||
import cloud.kubelet.foundation.core.abstraction.CoreFeature
|
||||
import org.koin.dsl.module
|
||||
import org.quartz.Scheduler
|
||||
import org.quartz.impl.StdSchedulerFactory
|
||||
|
||||
class SchedulerFeature : CoreFeature {
|
||||
private val scheduler: Scheduler = StdSchedulerFactory.getDefaultScheduler()
|
||||
|
||||
override fun enable() {
|
||||
scheduler.start()
|
||||
}
|
||||
|
||||
override fun disable() {
|
||||
scheduler.shutdown(true)
|
||||
}
|
||||
|
||||
override fun module() = module {
|
||||
single { scheduler }
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package cloud.kubelet.foundation.core.features.scheduler
|
||||
|
||||
import org.quartz.Job
|
||||
import org.quartz.JobExecutionContext
|
||||
|
||||
class SchedulerRunner : Job {
|
||||
override fun execute(context: JobExecutionContext) {
|
||||
val f = context.jobDetail.jobDataMap["function"] as () -> Unit
|
||||
f()
|
||||
}
|
||||
}
|
@ -1,3 +1,11 @@
|
||||
# Configuration of backup scheduling, expressed by cron expressions.
|
||||
schedule:
|
||||
# Cron expression to use for the backup schedule.
|
||||
# Examples:
|
||||
# "0 3 * * *" -> every day at 3 AM
|
||||
# "0 3 * * SUN" -> every Sunday at 3 AM
|
||||
cron: ""
|
||||
|
||||
# Configuration of S3 service to upload back-ups to.
|
||||
s3:
|
||||
# The access key ID from your S3-compliant storage provider.
|
||||
|
3
foundation-core/src/main/resources/quartz.properties
Normal file
3
foundation-core/src/main/resources/quartz.properties
Normal file
@ -0,0 +1,3 @@
|
||||
org.quartz.scheduler.instanceName = Foundation
|
||||
org.quartz.threadPool.threadCount = 2
|
||||
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
|
Loading…
Reference in New Issue
Block a user