Persistence of State Machines |
Shows how to persist the current state of a state machine and how to resume from persistent storage
In case a process crashes or the process must be shut down for some other reason, it might sometimes be desired to resume the state machine execution at the state where it was before.
The StaMa StateMachine class provides the methods SaveState and Resume to save the state machine active state (and the history if present) to a Stream and to initialize the active state from a Stream.
The Resume may optionally execute entry actions or skip execution. It is up to the application to ensure that there is a consistent understanding regarding which conditions are given when the state machine has been resumed from a persisted state and resides within that state.
The following code shows how to use the SaveState and Resume methods:
StateMachineTemplate t = new StateMachineTemplate(); t.Region("State1", false); t.State("State1"); t.Transition("T1", "State2", "Event1"); t.EndState(); t.State("State2"); t.Transition("T2", "State1", "Event2"); t.EndState(); t.EndRegion(); // Create a state machine and start it StateMachine stateMachine1 = t.CreateStateMachine(); stateMachine1.Startup(); // stateMachine1 is now ready for receiving events stateMachine1.SendTriggerEvent("Event1"); // Check that stateMachine1 has executed transition "T1" to state "State2" if (stateMachine1.ActiveStateConfiguration.ToString() != t.CreateStateConfiguration("State2").ToString()) { throw new Exception("stateMachine1 in unexpected state"); } // Save the current state of stateMachine1 MemoryStream stream = new MemoryStream(); stateMachine1.SaveState(stream); stream.Flush(); // Might write to persistent storage when using FileStream instead // For demonstration purposes reset the MemoryStream to enable reading from it // Real applications would open a FileStream stream.Position = 0; // Create a new state machine using the same structure and resume from saved state StateMachine stateMachine2 = t.CreateStateMachine(); stateMachine2.Resume(stream, false); // stateMachine2 is ready for receiving events stateMachine2.SendTriggerEvent("Event2"); // Check that stateMachine2 has executed transition "T2" to state "State1" if (stateMachine2.ActiveStateConfiguration.ToString() != t.CreateStateConfiguration("State1").ToString()) { throw new Exception("stateMachine2 in unexpected state"); }