使用play 2.5在scala中创建计划任务

时间:2016-07-04 20:08:21

标签: scala playframework

我想在Play 2.5中创建一个计划任务。我找到了一些与此主题相关的资源,但没有一个是针对Play 2.5的。我发现this resource与我正在寻找的相关,看起来不错。同样在同一链接上有一个从2.4到2.5的迁移指南。

旧版本的示例使用GlobalSettings作为基础,但在2.5中已弃用。迁移指南很重要,因为它说我们应该使用依赖注入而不是扩展这个特性。我不知道该怎么做。

你能给我一些指导吗?

2 个答案:

答案 0 :(得分:8)

你需要在Akka Actor中运行已经完成的任务:

<强> SchedulerActor.scala

package scheduler

import javax.inject.{Inject, Singleton}

import akka.actor.Actor
import org.joda.time.DateTime
import play.api.Logger

import scala.concurrent.ExecutionContext

@Singleton
class SchedulerActor @Inject()()(implicit ec: ExecutionContext) extends Actor {
  override def receive: Receive = {
    case _ =>
      // your job here
  }
}

<强> Scheduler.scala

package scheduler

import javax.inject.{Inject, Named}

import akka.actor.{ActorRef, ActorSystem}
import play.api.{Configuration, Logger}

import scala.concurrent.ExecutionContext
import scala.concurrent.duration._

class Scheduler @Inject() (val system: ActorSystem, @Named("scheduler-actor") val schedulerActor: ActorRef, configuration: Configuration)(implicit ec: ExecutionContext) {
  val frequency = configuration.getInt("frequency").get
  var actor = system.scheduler.schedule(
    0.microseconds, frequency.seconds, schedulerActor, "update")

}

<强> JobModule.scala

package modules

import com.google.inject.AbstractModule
import play.api.libs.concurrent.AkkaGuiceSupport
import scheduler.{Scheduler, SchedulerActor}

class JobModule extends AbstractModule with AkkaGuiceSupport {
  def configure() = {
    bindActor[SchedulerActor]("scheduler-actor")
    bind(classOf[Scheduler]).asEagerSingleton()
  }
}

<强> application.conf

play.modules.enabled += "modules.JobModule"

答案 1 :(得分:0)

如果您不想使用akka,可以使用java:

  • ScheduledFuture
  • ScheduledExecutorService的

<强> DemoDaemon.scala:

import java.util.concurrent.{Executors, ScheduledFuture, TimeUnit}
import javax.inject._
import play.Configuration
import scala.util.Try

class DemoDaemon @Inject() (conf: Configuration) {

  val isEnabled = conf.getBoolean("daemon.enabled")
  val delay = conf.getLong("daemon.delay")

  private var scheduledTaskOption : Option[ScheduledFuture[_]] = None

  def task(): Unit = {

    Try {
      println("doSomething")
    } recover {
      case e: Throwable => println(e.getMessage)
    }
  }

  def start(): Unit = {
    if (isEnabled) {
      val executor = Executors.newScheduledThreadPool(1)

      scheduledTaskOption = Some( 
        executor.scheduleAtFixedRate(
          new Runnable {
            override def run() = task()
          },
          delay, delay, TimeUnit.SECONDS
        )
      )
    } else {
      println("not enabled")
    }
  }

  def stop(): Unit = {
    scheduledTaskOption match {
      case Some(scheduledTask) =>
        println("Canceling task")
        val mayInterruptIfRunning = false
        scheduledTask.cancel(mayInterruptIfRunning)
      case None => println("Stopped but was never started")
    }
  }
}

<强> DaemonService.scala

import javax.inject.Inject
import play.api.inject.ApplicationLifecycle
import scala.concurrent.Future

class DaemonService @Inject() (appLifecycle: ApplicationLifecycle, daemon: DemoDaemon) {

  daemon.start()

  appLifecycle.addStopHook{ () =>
    Future.successful(daemon.stop())
  }
}

<强> JobModule.scala

import com.google.inject.AbstractModule

class JobModule extends AbstractModule {
  def configure(): Unit = {
    bind(classOf[DaemonService]).asEagerSingleton()
  }
}

<强> application.conf

daemon.enabled = true
daemon.delay = 10
play.modules.enabled += "com.demo.daemon.JobModule"