问题
In the receive method of a persistent actor, I receive a bunch a events I want to persist, and only after all events are persisted, update again my state. How can I do that?
def receive: Receive = {
...
case NewEvents(events) =>
persist(events) { singleEvent =>
// Update state using this single event
}
// After every events are persisted, do one more thing
}
Note that the persist() call is not blocking so I cannot put my code just after that.
Update: Why I need this
These new events come from an external web-service. My persistent actor needs to store in its state the last event id, which will be used for the subsequent ws call when it receives a command. The thing is that these commands may come concurrently, so I need some kind of locking system:
- Received ws call command: stash next commands until this one finishes (that is, to sum up, a boolean)
- Received responses from ws: store them, update the state and save the last id, execute another, single ws call for all commands that are in the stash (I'm keeping the command senders to be able to respond to them all once done) otherwise don't stash commands anymore.
回答1:
I haven't tried defer
yet, my initial solution was to send myself a PersistEventsDone
message. It works because the persist
method will stash all incoming messages until all the events handlers are executed. If another command came in the process, it doesn't really matter if it's before or after PersistEventsDone
:
def receive: Receive = {
...
case PersistEventsDone =>
...
case NewEvents(events) =>
persist(events) { singleEvent =>
// Update state using this single event
}
self ! PersistEventsDone
}
defer
is a bit weird in my case because it requires an event I don't need. But it still looks more natural than my solution.
来源:https://stackoverflow.com/questions/27549494/update-actor-state-only-after-all-events-are-persisted