我正在寻找关于akka调度程序用法的一些示例。我有一个actor(让我们调用它 - dataProducer)实现从一些数据库中检索数据。我想编写一个调度程序actor,它将在5秒的时间间隔内对dataProducer actor进行极化。如果数据检索比调度程序间隔花费更多时间,那么如何处理这种情况。调度程序actor中的scheduleOnce方法会处理这个吗?
这是我的调度程序演员
import java.util.concurrent.{Executors, TimeUnit}
import akka.actor.{Actor, Cancellable, Props}
import scala.concurrent.ExecutionContext
class SchedulerActor(interval: Long) extends Actor with LogF{
implicit val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(100))
private var scheduler: Cancellable = _
override def preStart(): Unit = {
import scala.concurrent.duration._
scheduler = context.system.scheduler.schedule(
initialDelay = 0 seconds,
interval = FiniteDuration(interval, TimeUnit.SECONDS),
receiver = self,
message = FetchData
)
}
override def postStop(): Unit = {
scheduler.cancel()
}
def receive = {
case FetchData =>
logger.debug( "Fetch Data" )
sender() ! "Data Fetched!!!" //here I'll call dataProducer API
true
case unknown =>
throw new RuntimeException( "ERROR: Received unknown message [" + unknown + "], can't handle it" )
}
}
object SchedulerActor {
def props(interval: Long): Props = Props(new SchedulerActor(interval))
}
sealed trait FetchDataMessage
case object FetchData extends FetchDataMessage
答案 0 :(得分:0)
计划程序scheduleOnce
有助于在延迟一段时间后执行。
具有不同的状态并在状态之间切换以接受不同类型的消息并相应地采取行动。但是当超时发生时,scheduleOnce会将你带到timeoutState。
ScheduleOnce将帮助演员知道超时已经发生。
如果数据检索比调度程序间隔花费更多时间,如何处理这种情况?
如果数据获取超过指定时间,则actor状态更改timeoutState
并且在超时状态下说明应该对actor执行的操作。您可以重试或尝试不同的来源。
我想编写一个调度程序actor,它将在5秒间隔内使dataProducer actor处于极点
在结果状态中等待scheduleOnce,延迟时间为5秒,以请求dataProducer并重复整个事件。
检查此代码以了解如何完成。
import akka.actor.{Actor, Cancellable}
import stackoverflow.DBUtils.Entity
import scala.concurrent.Future
import scala.concurrent.duration._
import akka.pattern.pipe
object DBPollActor {
case class Result(results: List[Entity])
case object Schedule
case object Timeup
case object FetchData
}
object DBUtils {
case class Entity(name: String)
def doDBOperation: Future[List[Entity]] = {
Future.successful(List(Entity(name = "foo")))
}
}
class DBPollActor(timeout: Int) extends Actor {
import DBPollActor._
implicit val ex = context.system.dispatcher
var schedulerOpt: Option[Cancellable] = None
@scala.throws[Exception](classOf[Exception])
override def preStart(): Unit = {
super.preStart()
self ! FetchData
schedulerOpt = Some(context.system.scheduler.scheduleOnce(timeout seconds) {
context become timeoutState
self ! Timeup
})
}
override def receive: Receive = {
case msg@FetchData =>
context become startState
self forward msg
}
def startState: Receive = {
case FetchData =>
schedulerOpt.map(_.cancel())
context become resultState
DBUtils.doDBOperation.map(Result) pipeTo self
schedulerOpt = Some(context.system.scheduler.scheduleOnce(timeout seconds) {
context become timeoutState
self ! Timeup
})
}
def timeoutState: Receive = {
case Timeup =>
schedulerOpt.map(_.cancel())
//Timeout happened do something or repeat
}
def resultState: Receive = {
case result@Result(list) =>
schedulerOpt.map(_.cancel())
//Result available consume the result and repeat or doSomething different
context become resultState
DBUtils.doDBOperation.map(Result) pipeTo self
schedulerOpt = Some(context.system.scheduler.scheduleOnce(timeout seconds) {
context become timeoutState
self ! Timeup
})
case ex: Exception =>
schedulerOpt.map(_.cancel())
//future failed exit or retry
}
}