Zanim przejdziemy do konkretnych problemów, musimy poznać przynajmniej podstawowe elementy AKKA.NET. W poprzednim wpisie opisałem jak definiować wiadomości oraz aktorów. Dzisiaj przejdziemy do kolejnego, bardzo ważnego elementu – przełączanie stanów. Jest to podstawowy element zarówno w modelu aktor, jak i w jakichkolwiek maszynach stanów (FSM). W poprzednim przykładzie przelewu środków z jednego konta na drugie, użyliśmy właśnie przełączania stanów. Dla przypomnienia:
class TransferActor { public void OnTransferMessageReceived(TransferMessage transferMessage) { ActorsSystem.GetActor(transferMessage.From).Send(new WithdrawMessage(transferMessage.Amount)); Context.Become(AwaitFrom(transferMessage.From,transferMessage.To,transferMessage.Amount)); } public void AwaitFrom(string from, string to, int amount) { ActorsSystem.GetActor(to).Send(new DepositMessage(amount)); Context.Became(AwaitTo(transferMessage.From, transferMessage.To, transferMessage.Amount)); } }
Po otrzymaniu zapytania o przesłaniu pieniędzy, przełączamy się w stan AwaitFrom. Po otrzymaniu potwierdzenia, składamy depozyt i znów czekamy na potwierdzenie.
W AKKA.NET zmiana stanu odbywa się za pomocą metody Become:
public class SampleActor : UntypedActor { protected override void OnReceive(object message) { Console.WriteLine("Otrzymano wiadomosc ze stanu I {0}",message); Become(GoToState2); } private void GoToState2(object message) { Console.WriteLine("Otrzymano wiadomosc ze stanu II {0}", message); } }
Po otrzymaniu pierwszej wiadomości, przełączamy się do stanu drugiego, reprezentowanego przez metodę GoToState2. Od tego momentu wszystkie wiadomości będą obsługiwane przez GoToState2, a nie OnReceive. Odpalmy zatem następujący kod:
var system = ActorSystem.Create("JakasNazwa"); var actor1 = system.ActorOf<SampleActor>(); for (int i = 0; i < 10; i++) { actor1.Tell(i.ToString()); }
Na ekranie zobaczymy najpierw tekst “Otrzymano wiadomosc ze stanu I”, a potem 9 razy “Otrzymano wiadomosc ze stanu II”.
Druga przydatna i alternatywna metoda to BecomeStacked. Podobnie jak Become służy do przełączania stanu. Tym razem jednak, stan będzie przechowywany na stosie, zatem będzie można go potem zdjąć i powrócić do poprzedniego. Przykład:
public class SampleActor : UntypedActor { protected override void OnReceive(object message) { Console.WriteLine("Otrzymano wiadomosc ze stanu I {0}",message); BecomeStacked(GoToState2); } private void GoToState2(object message) { Console.WriteLine("Otrzymano wiadomosc ze stanu II {0}", message); UnbecomeStacked(); } }
Po odpaleniu, na zmianę będziemy mieć stan I oraz II. Oczywiście nie jesteśmy ograniczeni wyłącznie do dwóch stanów.