0

私はPersistentActor、特定のイベントに対して、彼の状態や行動を変化させることができる を持っています。状態を永続化するために問題はありませんが、状態の一部として動作を永続化する必要があることがわかりました。そうしないと、スナップショットからの障害回復の場合に正しく初期化されません。状態であり、動作ではありません。これを正しく達成する方法は?

現在、状態と動作のタプルを保存していますが、これが正しい方法かどうかはわかりません。私はあらゆる種類の提案やアイデアを受け入れます。FWIW、この種のアクターの使用例は、クラスター シャーディングのエントリです。ここでは、各エントリが (become/unbecome) を使用していくつかの状態を通過し、エントリの状態とその動作を保持する必要があります。どうもありがとう。

問題を示すコードは次のとおりです。

class FooActor extends PersistentActor with ActorLogging {
  import FooActor._

  var state: List[String] = Nil

  def updateState(e: FooEvent): Unit = e match {
    case Initialized   ⇒ context become initialized
    case Uninitialized ⇒ context become uninitialized
    case Fooed(data)   ⇒ state = data :: state
  }

  def uninitialized: Receive = {
    case Init      ⇒ persist(Initialized)(updateState)
  }

  def initialized: Receive = {
    case Foo(data) ⇒ persist(Fooed(data))(updateState)
    case Uninit    ⇒ persist(Uninitialized)(updateState)
    case Snap      ⇒ saveSnapshot((state, receiveCommand)) // how to persist current behavior also?
  }

  def receiveRecover: Receive = {
    case e: FooEvent                              ⇒ updateState(e)
    // here, if I don't persist the behavior also, when the state is
    // recovered, the actor would be in the uninitialized behavior and 
    // thus will not process any Foo commands
    case SnapshotOffer(_, (_state: List[String], behavior: Receive)) ⇒
      state = _state
      context become behavior
  }

  def receiveCommand: Receive = uninitialized

  val persistenceId = "foo-pid"
}

object FooActor {
  case object Init
  case object Uninit
  case object Snap
  case class Foo(data: String)
  trait FooEvent
  case object Initialized extends FooEvent
  case object Uninitialized extends FooEvent
  case class Fooed(data: String) extends FooEvent
}
4

1 に答える 1