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

How to schedule complex tasks using Scala/Play 2.3?

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

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

问题是我想做一些比在这里记录更复杂的事情,我想更新数据库,所以我想调用模型文件中的一些函数 (models/SomeTable.scala) ,但我无法在 Global.scala.

中导入该代码

听起来如果我想做更复杂的事情,我应该使用 Akka 的 actor 系统,但我还远未理解它是如何工作的。我找到了有关如何通过 Akka's documentation 创建 Actors 的文档,但尚不清楚如何将其合并到我的 Play 项目中。我在哪里写这个 Actor class,它是如何导入的(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?

在此先致谢!

首先你肯定需要阅读有关 akka 的内容。

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

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
}

这里有一个演员 class。使用 preStart 和 postStop(阅读更多关于 actors lifecycle)定义和取消的时间表。计划的操作正在向 self 发送 Tick 消息(换句话说,演员将每 24 小时收到一次 Tick 消息,如果 receive 被定义为 Tick,则此消息将被处理)。 所以你只需要在我发表评论的地方开始实施。

从全球开始,您只需在 onStart:

中开始此操作
Akka.system.actorOf(MyActor.props, MyActor.Name)