Reputation: 5763
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 {
}
As example described
How could I init the actor state before accepting any other commands ?
Upvotes: 1
Views: 180
Reputation: 6242
You can use different behaviors:
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 {
}
You can even remove the mutable state altogether by passing it as parameters to the initialized
behavior (e.g. initialized(state)
).
And regarding the recovery, from official Akka docs:
It's also possible to switch between different command handlers during normal processing and recovery with context.become() and context.unbecome(). To get the actor into the same state after recovery you need to take special care to perform the same state transitions with become and unbecome in the receiveRecover method as you would have done in the command handler. Note that when using become from receiveRecover it will still only use the receiveRecover behavior when replaying the events. When replay is completed it will use the new behavior.
Upvotes: 3