如何使用Scala / Play 2.3安排复杂的任务?

时间:2018-02-25 19:36:03

标签: scala playframework-2.3

我希望计划每天运行一次,我想要运行的代码涉及对数据库中的条目进行更新。我已经设法通过使用Akka覆盖Global.scala中的onStart方法来安排运行一些简单的代码,如下所示

override def onStart(app: Application) = {
    Akka.system.scheduler.schedule(0.second, 1.second) {
        println("hello!")
    }
}

问题是我想做一些比登录更复杂的事情,我想对数据库进行更新,所以我想在模型文件中调用一些函数(models / SomeTable.scala),但我可以不要在Global.scala中导入该代码。

听起来好像我想要做一些更复杂的事情,我应该使用Akka的演员系统,但我还远未理解它是如何工作的。我已经找到了如何通过Akka's documentation创建Actors的文档,但是如何将它合并到我的Play项目中还不清楚。我在哪里编写这个Actor类,以及如何导入(允许Global.scala访问..?)?如果我不需要使用演员,那么有没有人对Play项目的这一部分中的导入和工作方式有所了解?

请注意,Play框架的这一部分经历了从Play版本2.3。*到2.4。*的大变化,所以绝对不应该期望2.4。*中的解决方案可能在这里工作

我上面得到的信息主要来自Play's documentation,还有一堆相关的SO问题:

How to schedule task daily + onStart in Play 2.0.4?

how to write cron job in play framework 2.3

Scheduling delaying of jobs tasks in Play framework 2.x app

Where is the job support in Play 2.0?

Was asynchronous jobs removed from the Play framework? What is a better alternative?

提前非常感谢!

1 个答案:

答案 0 :(得分:1)

首先,你一定要阅读有关akka的信息。

但是对于您的特定任务,您无需将任何内容导入Global。你只需要开始你的工人演员。这个演员可以自己安排定期行动。作为模板

import akka.actor.{Actor, Cancellable, Props}
import scala.concurrent.duration._

class MyActor extends Actor {
  private var cancellable: Option[Cancellable] = None


  override def preStart(): Unit = {
    super.preStart()
    cancellable = Some(
      context.system.scheduler.schedule(
        1.second,
        24.hours,
        self,
        MyActor.Tick
      )(context.dispatcher)
    )
  }

  override def postStop(): Unit = {
    cancellable.foreach(_.cancel())
    cancellable = None
    super.postStop()
  }

  def receive: Receive = {
    case MyActor.Tick =>
        // here is the start point for your execution
        // NEW CODE WILL BE HERE
  }
}

object MyActor {
  val Name = "my-actor"
  def props = Props(new MyActor)
  case object Tick
}

这里有一个演员类。使用preStart和postStop(详细了解actors lifecycle)定义和取消的计划。预定的操作是向Tick发送self条消息(换句话说,演员将收到每个24小时Tick条消息,如果receive定义为Tick,则会显示此消息将被处理)。 所以你只需要在我发表评论的地方开始实施。

从全局您只需要在onStart中启动此操作:

Akka.system.actorOf(MyActor.props, MyActor.Name)