2016-04-15 44 views
2

我有一個執着的演員。當它第一次啓動時(數據庫爲空),我堅持一些初始數據。但是這個州並沒有像我期望的那樣得到更新。它只有在處理完第一條消息後纔會更新。我怎樣才能讓演員在狀態更新後開始處理消息?阿卡堅持恢復完成更新狀態後第一條消息

演員代碼

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

一件事是,你通常不會更新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:詮釋)

//命令

的情況下添加類(v:智力)

希望這可以讓它更清晰一點。