Akka向init'PersistentActor`推荐实践

时间:2016-04-06 08:36:38

标签: scala akka akka-persistence

case class State(id: Long, remain: Int) {
  def take(t: Take) = copy(remain = remain - t.amount) 
}

object StateService {
  def getInitState(id: Long): Future[State]
}

sealed trait Evt
case class Init(id: Long) extends Evt
case class Take(id: Long, amount: Int) extends Evt

class FooActor extends PersistentActor  {
  var state: State

  def receiveCommand = {
    case Init(id) => ??? // how to
    case t: Take => persistAsync(t) {case e => state = state.take(t)}
  }
}

object FooActor {

}

如所描述的那样

如何在接受任何其他命令之前初始化actor状态?

1 个答案:

答案 0 :(得分:3)

您可以使用不同的行为:

case class State(id: Long, remain: Int)

object StateService {
  def getInitState(id: Long): Future[State]
}

sealed trait Evt
case class Init(id: Long) extends Evt

class FooActor extends PersistentActor  {
  var state: State

  import akka.pattern.pipe

  def notInitialized: Receive = {
    case Init(id) => 
      // for simplicity, failure is not handled
      StateService.getInitState(id) pipeTo self
    case st: State =>
      state = st
      context become initialized
  }

  def initialized: Receive = {
    case _ => // meh
  }

  def receiveCommand = notInitialized
}

object FooActor {

}

您甚至可以通过将其作为参数传递给initialized行为(例如initialized(state))来完全删除可变状态。 关于恢复,来自官方Akka文档:

  

在此期间,也可以在不同的命令处理程序之间切换   使用context.become()和。进行正常处理和恢复   context.unbecome()。让演员进入同一状态之后   恢复你需要特别小心,以执行相同的状态   转换为在receiveRecover方法中成为和不成为   你会在命令处理程序中完成的。请注意,使用时   从receiveRecover变成它仍然只会使用receiveRecover   重放事件时的行为。当重播完成时它会   使用新行为。