Akka quartz scheduler does not trigger the jobs

2019-08-27 12:40发布

问题:

I try to use this akka-quartz-scheduler in my play project. I created two akka actors, added configuration for actors:

akka {
  quartz {
    schedules {
      HELLO_ACTOR {
        description = "A cron job that fires off every 10 seconds"
        expression = "0/10 0 0 ? * * *"
      }
      CLEANUP_ACTOR {
        description = "A cron job that fires off every 10 seconds"
        expression = "0/10 0 0 ? * * *"
      }
    }
  }
}

I created module and add scheduler where i bind actors and scheduler:

protected void configure() {
        bindActor(HelloActor.class, HelloActor.NAME);
        bindActor(CleanupRunner.class, CleanupRunner.NAME);
        bind(QuartzSchedulerHelper.class).asEagerSingleton();
        bind(QuartzSchedulerExtension.class).toProvider(SchedulerJobInitializer.class);
    }


    private static class SchedulerJobInitializer implements Provider<QuartzSchedulerExtension> {
        private final QuartzSchedulerExtension quartzSchedulerExtension;

        @Inject
        public SchedulerJobInitializer(ActorSystem actorSystem) {
            this.quartzSchedulerExtension = new QuartzSchedulerExtension((ExtendedActorSystem) actorSystem);
        }

        @Override
        public QuartzSchedulerExtension get() {
            return quartzSchedulerExtension;
        }
    }

When application starts, I see in the log that actors were added to scheduler:

2018-07-06 11:51:44,947 [INFO] from org.quartz.impl.DirectSchedulerFactory in play-dev-mode-akka.actor.default-dispatcher-2 - Quartz scheduler 'QuartzScheduler~application

2018-07-06 11:51:44,947 [INFO] from org.quartz.impl.DirectSchedulerFactory in play-dev-mode-akka.actor.default-dispatcher-2 - Quartz scheduler version: 2.2.3

2018-07-06 11:51:44,950 [INFO] from org.quartz.core.QuartzScheduler in play-dev-mode-akka.actor.default-dispatcher-2 - Scheduler QuartzScheduler~application_$_application started.

2018-07-06 11:51:44,974 [INFO] from com.typesafe.akka.extension.quartz.QuartzSchedulerExtension in application-akka.actor.default-dispatcher-2 - Setting up scheduled job 'HELLO_ACTOR', with 'com.typesafe.akka.extension.quartz.QuartzCronSchedule@6a6c7b3b'

2018-07-06 11:51:45,005 [INFO] from com.typesafe.akka.extension.quartz.QuartzSchedulerExtension in application-akka.actor.default-dispatcher-2 - Setting up scheduled job 'CLEANUP_ACTOR', with 'com.typesafe.akka.extension.quartz.QuartzCronSchedule@2c32247d'

Acotrs should be triggered every 10 seconds. Any reason why this do not work, or what should I add and where?

Here is code on the github.

回答1:

You still need to schedule in the code to declare which message needs to be sent and to which actor. In Scala you would do:

QuartzSchedulerExtension(context.system).schedule("HELLO_ACTOR", someActor, "Hello from the Quartz scheduler")
QuartzSchedulerExtension(context.system).schedule("CLEANUP_ACTOR", someOtherActor, "Clean up from the Quartz scheduler")

If you want to stop one of these you can use the method cancelJob:

QuartzSchedulerExtension(context.system).cancelJob("HELLO_ACTOR")


回答2:

Your log snippet does not indicate that your actors are registered with the scheduler. What it does show is that the Quartz jobs are successfully scheduled: in your configuration, akka.quartz.schedules.HELLO_ACTOR and akka.quartz.schedules.CLEANUP_ACTOR are jobs, not actors, despite what you've named them. (I recommend renaming those jobs to avoid confusion.)

Considering your QuartzSchedulerHelper, it doesn't appear that your actors are registered with the scheduler:

List<String> actors = Arrays.asList(HelloActor.NAME, CleanupRunner.NAME);
for (String name : actors) {
  ActorRef actor = registry.actorFor(name);
  schedule(quartzSchedulerExtension, actor, name, RandomStringUtils.randomAlphabetic(10));
}

actorFor takes an actor path as an argument. What you're passing to that method is the actor's name. Use the actor path:

String actorPath = "/user/" + name
ActorRef actor = registry.actorFor(actorPath)

You might also want to try the following actor path:

String actorPath = "akka://application/user/" + name