Как запланировать почасовую работу с Play Framework 2.1?

В Play 1 это было просто:

@Every(value = "1h")
public class WebsiteStatusReporter extends Job {

    @Override
    public void doJob() throws Exception {
        // do something
    }
}

Что эквивалентно для Play 2.1?

Я знаю, что Play использует akka, а я нашел этот пример кода:

import play.api.libs.concurrent.Execution.Implicits._
Akka.system.scheduler.schedule(0.seconds, 30.minutes, testActor, "tick")

Но, будучи Scala noob, я не понимаю, как это работает. Может ли кто-нибудь предоставить полный рабочий пример (от конца до конца)?

Ответ 1

Вот выдержка из моего кода:

import scala.concurrent.duration.DurationInt
import akka.actor.Props.apply
import play.api.Application
import play.api.GlobalSettings
import play.api.Logger
import play.api.Play
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import play.api.libs.concurrent.Akka
import akka.actor.Props
import actor.ReminderActor

object Global extends GlobalSettings {

  override def onStart(app: Application) {

    val controllerPath = controllers.routes.Ping.ping.url
    play.api.Play.mode(app) match {
      case play.api.Mode.Test => // do not schedule anything for Test
      case _ => reminderDaemon(app)
    }

  }

  def reminderDaemon(app: Application) = {
    Logger.info("Scheduling the reminder daemon")
    val reminderActor = Akka.system(app).actorOf(Props(new ReminderActor()))
    Akka.system(app).scheduler.schedule(0 seconds, 5 minutes, reminderActor, "reminderDaemon")
  }

}

Он просто запускает демон в начале приложения, а затем каждые 5 минут. Он использует Play 2.1 и работает как ожидалось.

Обратите внимание, что этот код использует Глобальный объект, который позволяет запускать некоторый код при запуске приложения.

Ответ 2

Пример:

case object Tick

class TestActor extends Actor {

  def receive = {
    case Tick => //...
  }
}

val testActor = Akka.system.actorOf(Props[TestActor], name = "testActor")

Akka.system.scheduler.schedule(0.seconds, 30.minutes, testActor, Tick)

Ответ 3

Взгляните на Akka doc

который вы дали:

def schedule(
  initialDelay: Duration,
  frequency: Duration,
  receiver: ActorRef,
  message: Any): Cancellable

Значит: начните через 0 секунд, каждые 30 минут отправьте актеру сообщение testActor Tick

что еще для простых задач, которые вы, вероятно, не наделите, вам нужно использовать Actors - вы можете просто запланировать новый Runnable:

  def schedule(
    initialDelay: Duration, frequency: Duration, runnable: Runnable): Cancellable

Более подробное описание в другом ответе

Ответ 4

Простой игровой планировщик без использования Актеров.

Это можно сделать с помощью org.quartz.scheduler и вызвать планировщика из глобального класса.

Пример планировщика