1
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 {

}

如示例所述

我怎么能在接受任何其他命令之前初始化演员状态?

4

1 回答 1

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() 在不同的命令处理程序之间切换。要让actor在恢复后进入相同的状态,您需要特别注意在receiveRecover 方法中使用become 和unbecome 执行相同的状态转换,就像您在命令处理程序中所做的那样。请注意,当使用 become from receiveRecover 时,它仍然只会在重放事件时使用 receiveRecover 行为。重播完成后,它将使用新行为。

于 2016-04-06T08:43:10.330 回答