Планирование задания в определенное время суток с помощью Akka - программирование
Подтвердить что ты не робот

Планирование задания в определенное время суток с помощью Akka

Я начинаю с Аккой. Мне нужно планировать задачу каждый день в определенное время дня, скажем, 8 утра. То, что я знаю, как это делать, - это планирование задачи периодически, например

import akka.util.duration._

scheduler.schedule(0 seconds, 10 minutes) {
  doSomething()
}

Каков самый простой способ запланировать задания в определенное время суток в Akka?

Маленькая скобка

Легко сделать то, что я хочу, просто используя эту функцию. Реализация игрушки будет выглядеть как

scheduler.schedule(0 seconds, 24 hours) {
  val now = computeTimeOfDay()
  val delay = desiredTime - now

  scheduler.scheduleOnce(delay) {
    doSomething()
  }
}

Это не сложно, но я ввел небольшое условие гонки. На самом деле, подумайте, что произойдет, если я запустил это перед 8AM. Внешнее закрытие начнется, но к моменту вычисления delay мы можем после 8AM. Это означает, что внутреннее закрытие, которое должно выполнить сразу же, будет перенесено на завтра, тем самым пропустив выполнение на один день.

Есть способы исправить это состояние гонки: например, я мог выполнять чек каждые 12 часов и вместо того, чтобы планировать задачу сразу, отправляя ее актеру, который не будет принимать более одной задачи за раз.

Но, вероятно, это уже существует в Akka или в каком-то расширении.

4b9b3361

Ответ 1

Напишите один раз, запустите каждый день

val GatherStatisticsPeriod = 24 hours

private[this] val scheduled = new AtomicBoolean(false)

def calcBeforeMidnight: Duration = { 
  // TODO implement 
} 

def preRestart(reason: Throwable, message: Option[Any]) {
  self ! GatherStatisticsScheduled(scheduled.get)
  super.preRestart(reason, message)
}

def schedule(period: Duration, who: ActorRef) = 
  ServerRoot.actorSystem.scheduler
    .scheduleOnce(period)(who ! GatherStatisticsTick)

def receive = {

  case StartServer(nodeName) => 
    sender ! ServerStarted(nodeName)
    if (scheduled.compareAndSet(false, true)) 
      schedule(calcBeforeMidnight, self)

  case GatherStatisticsTick =>
    stats.update
    scheduled.set(true)
    schedule(GatherStatisticsPeriod, self) 

  case GatherStatisticsScheduled(isScheduled) =>
    if (isScheduled && scheduled.compareAndSet(false, isScheduled))
      schedule(calcBeforeMidnight, self)

}

Я считаю, что планировщик Akka управляет перезагрузкой внутри, так или иначе. Я использовал непостоянный способ отправки сообщения самому себе - на самом деле не было строгой гарантии доставки. Кроме того, тики могут отличаться, поэтому функция GatherStatisticsPeriod может быть функцией.

Ответ 2

Чтобы использовать этот вид планирования в Akka, вам придется сворачивать свой собственный или, возможно, использовать Quartz, либо через Akka Camel, либо это прототип кварца для akka.

Если вам не нужны какие-либо фантазии и очень точные данные, я бы просто вычислил задержку в желаемый первый раз и использовал это как стартовую задержку для вызова расписания и доверял интервалу.