View Source Xstate.StateMachine (xstate v0.1.0)

Xstate is split into 3 parts:

  • Machine: Struct used to build initialization for a machine consisting of state, events, and several other configurations.
  • Context: A payload or extended state that is passed through the before and callback function arguments, when the transition occurs
  • Transitions: Define how the machine reacts to events dynamically.

Concepts

A finite state machine is a mathematical model of computation that describes the behavior of a system that can be in only one state at any given time. For example, let's say you can be represented by a state machine with a finite number (2) of states: asleep or awake. At any given time, you're either asleep or awake. It is impossible for you to be both asleep and awake at the same time, and it is impossible for you to be neither asleep nor awake.

Formally, finite state machines have five parts:

  • A finite number of states
  • A finite number of events
  • An initial state
  • A transition function that determines the next state given the current state and event
  • A (possibly empty) set of final states

State refers to some finite, qualitative "mode" or "status" of a system being modeled by a state machine, and does not describe all the (possibly infinite) data related to that system. For example, water can be in 1 of 4 states: ice, liquid, gas, or plasma. However, the temperature of water can vary and its measurement is quantitative and infinite.

Layouts

  %StateMachine.Machine{
    initial_state: "created",
    mapping: %{
      :created => %{
      # ^ event
        :confirmed_by_customer => %StateMachine.Transitions{
          # ^ nested event
          target: "customer_confirmed",
          # ^ Value to be used for the next state
          before: nil,
          # ^ Function that's called before the transition occurs
          callback: nil
          # ^ Function that's called after the transition occurs
          #
          # Notes: `before` & `callback` has a parameter of type %Context{..}
          # e.g: before: fn context -> IO.inspect(context) end
        }
      },
      ...
    },
    modifiable_states: MapSet.new(["created"])
  }

Link to this section Summary

Functions

Check transition matches the event

Returns a specification to start this module under a supervisor.

Accessing the current state from the machine

Check is current state is modifiable

Construct a new machine

Invoke transition

Link to this section Types

@type t() :: %Xstate.StateMachine{
  external: term(),
  pid: pid(),
  states: Xstate.StateMachine.Machine.t()
}

Link to this section Functions

Link to this function

can_transition?(machine, event)

View Source
@spec can_transition?(t(), String.t() | atom()) :: boolean()

Check transition matches the event

Support for nested key, only 2 level (e.g: "create.customer_confirmed")

  StateMachine.can_transition?(state, event)

Returns a specification to start this module under a supervisor.

See Supervisor.

@spec get_states(Xstate.StateMachine.Machine.t()) :: term()

Accessing the current state from the machine

  StateMachine.get_states(machine)
Link to this function

modifiable?(machine, current_state)

View Source
@spec modifiable?(t(), term()) :: boolean()

Check is current state is modifiable

  current_state = StateMachine.get_states(state)
  StateMachine.modifiable?(machine, current_state)
Link to this function

new(states, external \\ nil)

View Source
@spec new(Xstate.StateMachine.Machine.t(), term()) :: t()

Construct a new machine

Parameters

  • state: The machine state you want to construct.
  • external: Any external value you want to pass it (e.g: ecto)
  StateMachine.new(...)
Link to this function

transition(machine, event)

View Source
@spec transition(Xstate.StateMachine.Machine.t(), String.t() | atom()) :: term()

Invoke transition

  • machine: the Machine
  • event: the event that causes the transition
   StateMachine.transition(state, :created)

   #  Nested?, should using string
   StateMachine.transition(state, "created.cancel")