2017-02-19 2 views
2

FSM Akka Acctor로 은근하게하고 싶습니다. 나는 stash()unstashAll()을 넣을 곳을 모른다.Akka FSM 배우 숨기기 및 빗대김으로

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 

고마워요.

답변

5

FSM에서 onTransition 메서드를 사용하면이 작업을 수행 할 수 있습니다. 이것은 상태 변경이 발생할 때 실행되고 우리는 그 순간을 사용하여 모든 메시지를 unstash 할 수 있습니다. stashing에 대해서는 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() 
    } 
} 

당신이 더 이상 질문 : 안드레이-t @ 많은, 작동

+0

감사이 있으면 알려주세요 : 당신이 상태 사이의 사이클 수 있도록 나 또한 작은 업데이 트를했습니다. – Rohit

+0

나는 듣고있어 기뻐요 :) –