Акка ФСМ Актер со скрытием и снятием
Я хотел бы делать скрытие / разборку с FSM Akka Acctor. Я не знаю, где поставить stash()
а также unstashAll()
,
У меня есть упрощенный пример ниже:
import akka.actor.{ActorSystem, FSM, Props, Stash}
trait TestState
case object StateA extends TestState
case object StateB extends TestState
case class TestData()
case class MessageA(msg: String)
case class MessageB(msg: String)
case object ChangeState
class TestFSM extends FSM[TestState, TestData] with Stash {
startWith(StateA, TestData())
when(StateA) {
case Event(MessageA(msgA), _) =>
println(s"In StateA: $msgA")
stay()
case Event(ChangeState, _) =>
println("Changing state from A to B")
goto(StateB)
}
when(StateB) {
case Event(MessageB(msgB), _) =>
println(s"In StateB: $msgB")
stay()
}
whenUnhandled {
case Event(e, _) =>
println(s"Unhandled event: $e")
stay()
}
}
object TestFSM extends App {
val system = ActorSystem("test-system")
val actor = system.actorOf(Props[TestFSM])
actor ! MessageA("Apple 1")
actor ! MessageB("Banana 1")
actor ! MessageA("Apple 2")
actor ! ChangeState
actor ! MessageB("Banana 2")
}
Начальное состояние StateA
, Когда в StateA
актер должен обрабатывать только сообщения типа MessageA
, Если он получает любой другой тип сообщения (за исключением ChangeState
) это должно спрятать это. После получения сообщения ChangeState
, актер должен измениться на StateB
, При переходе от StateA
в StateB
, он должен распаковать все сообщения. Когда в StateB
актер должен обрабатывать только сообщения типа MessageB
,
Я не уверен, где именно stash()
а также unstashAll()
для достижения этой цели.
Вывод, который я получаю при запуске:
In StateA: Apple 1
Unhandled event: MessageB(Banana 1)
In StateA: Apple 2
Changing state from A to B
In StateB: Banana 2
Вывод, который я хотел бы увидеть:
In StateA: Apple 1
In StateA: Apple 2
Changing state from A to B
In StateB: Banana 1
In StateB: Banana 2
Большое спасибо.
1 ответ
Вы можете достичь этого с помощью onTransition
метод на FSM
, Это выполняется, когда происходит изменение состояния, и мы можем использовать этот момент, чтобы распаковать все сообщения. Что касается скрытия, вам нужно сделать это в whenUnhandled
метод. Я также сделал небольшое обновление, чтобы вы могли переключаться между состояниями:
class TestFSM extends FSM[TestState, TestData] with Stash {
startWith(StateA, TestData())
when(StateA) {
case Event(MessageA(msgA), _) =>
println(s"In StateA: $msgA")
stay()
case Event(ChangeState, _) =>
println("Changing state from A to B")
goto(StateB)
}
when(StateB) {
case Event(MessageB(msgB), _) =>
println(s"In StateB: $msgB")
stay()
case Event(ChangeState, _) =>
println("Changing state from B to A")
goto(StateA)
}
/**
* Here we can stash all messages. For example when we're in state A,
* we handle both `MessageA` and `ChangeState` messages, but we don't
* handle `MessageB` instances which will end up here. The opposite
* happens when we're in state B.
*/
whenUnhandled {
case _: Event =>
stash()
stay()
}
// When transitioning into another state, unstash all messages.
onTransition {
case StateA -> StateB => unstashAll()
case StateB -> StateA => unstashAll()
}
}
Позвольте мне знать, если у вас есть еще вопросы:)