Akka在第一条消息后坚持恢复完成更新状态

时间:2016-04-15 14:09:18

标签: scala akka akka-persistence

我有一个持久的演员。当它第一次启动时(数据库为空)我会保留一些初始数据。但是国家没有像我预期的那样得到更新。只有在处理完第一条消息后才会更新。如何在状态更新后让actor开始处理消息?

演员代码

class TestActor extends PersistentActor {
  var numberOfEvents = 0

  def updateState(e: Any): Unit = {
    println("updating")
    numberOfEvents += 1
  }

  override def receiveRecover: Receive = {
    case RecoveryCompleted =>
      if (numberOfEvents == 0) {
        println("persisting")
        persist("foo")(updateState)
      }
  }

  override def receiveCommand: Receive = {
    case _ => {
      println("answering")
      sender ! numberOfEvents
    }
  }
}

测试代码

Await.result(actorRef ? "stats", Duration.Inf) shouldBe 0 // I wan't 1 here
Await.result(actorRef ? "stats", Duration.Inf) shouldBe 1

输出

persisting
answering // why this goes before updating?
updating
answering

Full code

1 个答案:

答案 0 :(得分:1)

您要重新考虑的一件事是,您通常不会更新RecoveryCompleted事件的状态,而是处理您持续重建状态的事件。 RecoveryCompleted消息用于处理恢复结束时要执行的操作。这些事件将是您持久保存的日志中重播的事件。如果您使用快照,还可以选择获取快照事件。

例如:

override def receiveRecover: Receive = {
    case Added(num) =>
        updateState(num) 

    case SnapshotOffer(metadata, snapshot) ⇒
       // Restore your full state from the data in the snapshot

    case RecoveryCompleted =>
        println("Recovery completed") // use logger here
  }

另一方面,receiveCommand用于处理传入的命令并持久保存这些事件,然后在更新这些事件后更新内部状态。

override def receiveCommand: Receive = {
    case Add(num) => {
      println("received event and persisting")

      persist(Added(num){ evt ⇒ 
        // This gets called after the persist succeeds
        updateState(num)
        sender ! numberOfEvents
      }      
    }
  }

def updateState(e: Int): Unit = {
    println("updating")
    numberOfEvents += e
  }

就消息传递而言,我发现将事件命名为命令的过去时非常有用,如下所示:

//活动

案例类已添加(v:Int)

//命令

案例类添加(v:Int)

希望这会让它更清晰一些。