app/schedule/BakeScheduler.scala (59 lines of code) (raw):
package schedule
import models.{BakeSchedule, Recipe, RecipeId}
import org.quartz.{JobDataMap, JobKey, Scheduler, TriggerKey}
import org.quartz.CronScheduleBuilder._
import org.quartz.JobBuilder._
import org.quartz.TriggerBuilder._
import services.Loggable
class BakeScheduler(
scheduler: Scheduler,
scheduledBakeRunner: ScheduledBakeRunner
) extends Loggable {
def initialise(recipes: Iterable[Recipe]): Unit = {
recipes.flatMap(r => r.bakeSchedule.map(s => (r.id, s))).foreach {
case (recipeId, bakeSchedule) => scheduleBake(recipeId, bakeSchedule)
}
}
def reschedule(recipe: Recipe): Unit = {
// Delete any job and trigger that we may have previously created
scheduler.deleteJob(jobKey(recipe.id))
// If the recipe has a bake schedule, schedule it
recipe.bakeSchedule.foreach { bakeSchedule =>
scheduleBake(recipe.id, bakeSchedule)
}
}
private def scheduleBake(
recipeId: RecipeId,
bakeSchedule: BakeSchedule
): Unit = {
val jobDetail = newJob(classOf[BakeJob])
.withIdentity(jobKey(recipeId))
.usingJobData(buildJobDataMap(recipeId))
.build()
val trigger = newTrigger()
.withIdentity(triggerKey(recipeId))
.withSchedule(cronSchedule(bakeSchedule.quartzCronExpression))
.build()
scheduler.scheduleJob(jobDetail, trigger)
log.info(
s"Scheduled recipe [$recipeId] to bake with schedule [${bakeSchedule.quartzCronExpression}]"
)
}
def start(): Unit = scheduler.start()
def shutdown(): Unit = scheduler.shutdown()
private def jobKey(recipeId: RecipeId): JobKey = new JobKey(recipeId.value)
private def triggerKey(recipeId: RecipeId): TriggerKey = new TriggerKey(
recipeId.value
)
private def buildJobDataMap(recipeId: RecipeId): JobDataMap = {
import BakeScheduler.JobDataKeys
val map = new JobDataMap()
map.put(JobDataKeys.RecipeId, recipeId)
map.put(JobDataKeys.Runner, scheduledBakeRunner)
map
}
}
object BakeScheduler {
object JobDataKeys {
val RecipeId = "recipeId"
val Runner = "runner"
}
}