2017-02-19 5 views
2

FSM Akka Acctorでstashing/unstashingしたいと思います。私はどこにstash()unstashAll()を置くべきかわからない。アクカFSM俳優隠しとアンダーシュート付き

Iは、以下の簡単な例を有する:初期状態はStateAある

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の場合、俳優は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

FSMonTransitionメソッドを使用すると、これを実現できます。これは、状態の変化が発生したときに実行され、その時点ですべてのメッセージをアンスタッシュできます。 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

私はそれを聞いてうれしいよ:) –