8

Trying to schedule tasks like this in Play Framework 2.4.2 Scala without luck:

import akka.actor.Actor
import play.api.libs.concurrent.Akka
import scala.concurrent.duration._
import play.api.Play.current
import scala.concurrent.ExecutionContext.Implicits.global

class Scheduler extends Actor {

  override def preStart() {
    val dbupdate = Akka.system.scheduler.schedule(
      0.microseconds, 5.minutes, self, "update")
    val pictureClean = Akka.system.scheduler.schedule(
      0.microseconds, 30.minutes, self, "clean")
  }

  def receive = {
    case "update" => updateDB()
    case "clean" => clean()
  }

  def updateDB(): Unit ={
    Logger.debug("updates running")
  }

  def clean(): Unit ={
    Logger.debug("cleanup running")
  }
}

Nothing is printed in console. What I'm doing wrong?

Jonik
  • 80,077
  • 70
  • 264
  • 372
sergeda
  • 2,061
  • 3
  • 20
  • 43

2 Answers2

21

Ok. Here working code of scheduler I've built: Module:

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

Scheduler:

class Scheduler @Inject() (val system: ActorSystem, @Named("scheduler-actor") val schedulerActor: ActorRef)(implicit ec: ExecutionContext)
{
  system.scheduler.schedule(
    0.microseconds, 5.minutes, schedulerActor, "update")
  system.scheduler.schedule(
    30.minutes, 30.days, schedulerActor, "clean")
}

Actor:

@Singleton
class SchedulerActor @Inject() (updater: Updater) extends Actor {
  def receive = {
    case "update" => updateDB()
    case "clean" => clean()
  }

  def updateDB(): Unit ={
    Logger.debug("updates running")
  }

  def clean(): Unit ={
    Logger.debug("cleanup running")
  }
}

You also need to add your module in application.conf:

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

Hope this will help someone

Jonik
  • 80,077
  • 70
  • 264
  • 372
sergeda
  • 2,061
  • 3
  • 20
  • 43
  • even though i've injected my application to the scheduler, it still throws an exception at runtime saying that my application has not started. (oh and by the way, what is updater?) – Roy Lin Aug 07 '15 at 05:53
  • When you say "add your module to application.conf", how exactly do you do that? Can you add that to the answer? – Jonik Jan 07 '16 at 15:38
  • At the `Scheduler` class, since you are already injecting an `ActorSytem`, you won't need to inject `Application` and then you won't need the `implicit app` too. After that, just change the `Akka.system.scheduler.schedule(...)` to use the injected system: `system.scheduler.schedule(...)`. – marcospereira Jan 15 '16 at 02:00
  • Thanks, this answer was very helpful! If anyone runs into "There is no started application" problems with this setup (especially with short or no initial delay for a task), make sure you’ve replaced uses of `Play.configuration` with injected `conf: Configuration` and `DB.withConnection` with injected `db: Database`, and other things mentioned in [2.4 migration guide](https://www.playframework.com/documentation/2.4.x/Migration24#Dependency-Injected-Components). – Jonik Jan 15 '16 at 12:07
  • 2
    @RoyLin: I think "updater" is the answerer's own code that would be used from a scheduled task. Simply remove it or replace with something *you* need injected (typically a service, UserService or whatever your needs are). – Jonik Jan 15 '16 at 12:14
  • what is the updater: Updater? is it a play scala import? – AlexCon Mar 21 '17 at 15:59
0

Try

context.system.scheduler.schedule

And also make sure you have logging at Debug level otherwise those messages won't make it to the console. If you're unsure try changing them to Logger.error temporarily.

mattinbits
  • 10,370
  • 1
  • 26
  • 35