在系统启动时安排重复演员播放2.4.3

问题描述 投票:0回答:2

我最近开始使用 Scala 和 Play Framework,并且刚刚将我一直在开发的服务升级到 Play 2.4.3。我的最终目标是创建一个夜间进程,在我的播放应用程序中启动一个服务方法,以便通过方法调用来安排事件,我当前正在使用 Actor 调用该方法。

我的基本想法是通过一个 Global.scala 文件来覆盖 onStart,但后来我看到了关于不再使用 GlobalSettings 的 play 文档 (https://www.playframework.com/documentation/2.4 .x/GlobalSettings)并一直在尝试将其转移到注入依赖项方法。

这是我迄今为止拼凑的内容:

模块代码:

import javax.inject._

import com.myOrganization.myPackage.Actors.ScheduleActor
import play.api.libs.concurrent.AkkaGuiceSupport
import play.libs.Akka
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import akka.actor.{ActorRef, ActorSystem}
import scala.concurrent.duration._
import play.Application

import com.google.inject.AbstractModule

@Singleton
class NightlyEvalSchedulerStartup @Inject()(system: ActorSystem, @Named("ScheduleActor") scheduleActor: ActorRef) {
  Akka.system.scheduler.schedule(10.seconds, 20.seconds, scheduleActor, "ScheduleActor")
}

class ScheduleModule extends AbstractModule with AkkaGuiceSupport {
  def configure() = {
    bindActor[ScheduleActor]("ScheduleActor")
    bind(classOf[NightlyEvalSchedulerStartup]).asEagerSingleton
  }
}

演员类别:

import akka.actor.{Actor, Props}
import com.myOrganization.myPackage.services.MySchedulingService

object ScheduleActor {
  def props = Props[ScheduleActor]

  class updateSchedules
}

class ScheduleActor extends Actor {
  val MySchedulingService: MySchedulingService = new MySchedulingService
  def receive = {
    case "runScheduler" => MySchedulingService.nightlyScheduledUpdate()
  }
}

应用程序.conf

play.modules.enabled += "com.myOrganization.myPackage.modules.ScheduleModule"

该服务正在调用主要基于 Scala 逻辑代码和通过 Anorm 进行数据库交互的方法。

每次我尝试使用 activator start 启动服务(或运行,一旦收到 Http 请求),都会收到以下错误:

Oops, cannot start the server.
com.google.inject.CreationException: Unable to create injector, see the following errors:

1) Error injecting constructor, java.lang.RuntimeException: There is no started application

我尝试通过用简单的 println() 替换 Aka.system.scheduler... 片段来运行相同的代码,一切似乎都工作正常,这意味着服务启动了,我在控制台上看到了我的消息。所以我猜测 Akka 调度程序缺少一些依赖,导致它崩溃。你能提供的任何建议都会很棒,我一整天都在努力反对这个问题。

编辑(根据请求解决的代码):

模块代码,添加了一些用于粗略估计第二天晚上凌晨 3 点的代码。这可能会改变,但现在有效:

package com.myOrganization.performanceManagement.modules

import com.myOrganization.performanceManagement.Actors.ScheduleActor
import com.myOrganization.performanceManagement.Actors.ScheduleActor.nightlySchedule
import org.joda.time.{Seconds, LocalDate, LocalTime, LocalDateTime}
import play.api.libs.concurrent.AkkaGuiceSupport
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import akka.actor.{ActorRef, ActorSystem}
import scala.concurrent.duration.{FiniteDuration, SECONDS, HOURS }
import org.joda.time._
import com.google.inject.{Inject, Singleton, AbstractModule}
import com.google.inject.name.Named

class ScheduleModule extends AbstractModule with AkkaGuiceSupport {
  override def configure() = {
    bindActor[ScheduleActor]("ScheduleActor")
    bind(classOf[NightlyEvalSchedulerStartup]).asEagerSingleton()
  }
}

@Singleton
class NightlyEvalSchedulerStartup @Inject()(system: ActorSystem, @Named("ScheduleActor") scheduleActor: ActorRef) {
  //Calculate initial delay to 3am the next day.
  val currentTime: DateTime = DateTime.now
  val targetDateTime = currentTime.plusDays(1).withTimeAtStartOfDay()

  //Account for Daylight savings to an extent, not mandatory that it starts at 3am, just after midnight.
  val initialDelaySeconds = targetDateTime.getHourOfDay match {
    case 0 => new Duration(currentTime, targetDateTime.plusHours(3)).getStandardSeconds
    case 1 => new Duration(currentTime, targetDateTime.plusHours(2)).getStandardSeconds
  }

  //Schedule first actor firing to occur at calculated delay and then every 24 hours.
  system.scheduler.schedule(FiniteDuration(initialDelaySeconds, SECONDS), FiniteDuration(24, HOURS), scheduleActor, nightlySchedule)
}

演员:

package com.myOrganization.performanceManagement.Actors

import akka.actor.{ActorSystem, Actor}
import com.google.inject.Inject
import com.myOrganization.performanceManagement.services.PMEvalSchedulingService

object ScheduleActor {
  case object nightlySchedule
}

class ScheduleActor @Inject() (actorSystem: ActorSystem) extends Actor {
  val pMEvalSchedulingService: PMEvalSchedulingService = new PMEvalSchedulingService
  override def receive: Receive = {
    case nightlySchedule =>
        println("Called the scheduler")
        pMEvalSchedulingService.nightlyScheduledEvaluationsUpdate()
  }
}
scala playframework akka playframework-2.4
2个回答
2
投票

就我而言,最大的问题最终是,当在 NightlyEvalSchedulerStartup() 中安排 actor 调用时,我正在调用 Akka.system...这导致系统在应用程序存在之前实例化一个新的 AkkaSystem。通过删除 akk 系统,代表已准备就绪的注入依赖项。希望这对将来的人有帮助!


0
投票

您还有其他需要改变的地方吗? 面临类似的问题 bindActorFactory...] 未在 Play Framework 应用程序启动时启动 actor

© www.soinside.com 2019 - 2024. All rights reserved.