enragedginger/akka-quartz-scheduler

Running multiple Play instances fires jobs multiple times

pybuche opened this issue · 3 comments

Hi,

I'm not exactly sure if this can be handled, but I'm struggling to find a way to have only one scheduler for my Play app that is deployed and replicated via Heroku.

I use the scheduler this way:
Module.scala

package fr.staycation

import com.google.inject.AbstractModule
import play.api.libs.concurrent.AkkaGuiceSupport
import play.api.{Configuration, Environment}

import fr.staycation.commons.scheduled.{TaskActor, TaskScheduler}


class Module(environment: Environment, conf: Configuration) extends AbstractModule with AkkaGuiceSupport {
  override def configure() = {
    bindActor[TaskActor]("task-actor")
    bind(classOf[TaskScheduler]).asEagerSingleton()
  }
}

TaskScheduler

package fr.staycation.commons.scheduled

import akka.actor.{ActorRef, ActorSystem}
import com.typesafe.akka.extension.quartz.QuartzSchedulerExtension
import com.typesafe.config.Config
import com.typesafe.scalalogging.StrictLogging
import javax.inject.{Inject, Named, Singleton}

import fr.staycation.commons.scheduled.Tasks._

import scala.concurrent.ExecutionContext


@Singleton
class TaskScheduler @Inject()(actorSystem: ActorSystem, @Named("task-actor") taskActor: ActorRef, config: Config)
  (implicit executionContext: ExecutionContext) extends StrictLogging {
    logger.info("Starting Scheduler...")
    val scheduler = QuartzSchedulerExtension.get(actorSystem)

    scheduler.schedule("ExpireBookings", taskActor, ExpireBookings)
    ...other schedules
}

And the TaskActor that handle Akka messages and execute jobs.

Everything is working well with one instance of my app, but if I replicate it, the scheduler fire as many events as there are instances...

In this part of the README, it says:

Because it is an Actor which provides no "Singleton"-like guarantee, it becomes too easy for users to accidentally spin up multiple scheduler instances, each of which is backed by its own threadpool. Instead, with akka-quartz-scheduler we use Akka's Extension system which provides a plugin model – we guarantee only one Quartz Scheduler is ever spun up per ActorSystem

But it looks like there are 2 Actor systems running independently... Am I missing something, how can I synchronize my 2 instances so that the scheduler fires event only once ?

Thanks !

Hi @pybuche,

Can you explain what you mean by "if I replicate it"? Are you talking about replicating your app on Heroku? Is it basically spinning up multiple instances of your Play application?

You need to setup the Play application in an Akka cluster to avoid having the same actor being spun up on both nodes. I was just looking at this issue now and was beginning to get afraid this is actually an issue, but as I conclude its an issue with missing Akka cluster configuration. Correct me if I am wrong. When both apps are in the same Akka cluster, there exists options to check that the actor does not exist in the cluster. Or sumtin sumtin. Until I need it, need to know basis :P

@jarlah I believe you're correct. I'm going to close this issue for now. Thanks for investigating.