Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Pretty State Machine

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for Jeff Smith Jeff Smith
February 28, 2019

Pretty State Machine

In this talk, Jeff will pull back the curtain on `gen_statem` and provide a useful reference for how and when to use it and why the apparent complexity might be worth it.

What are its strengths and weaknesses?

Is there anything `gen_statem` can do that `GenServer` can't?

In this talk, Jeff will explore these questions while providing some guidance and clarity on this mysterious behaviour available since the release of OTP 19.

Avatar for Jeff Smith

Jeff Smith

February 28, 2019

More Decks by Jeff Smith

Other Decks in Technology

Transcript

  1. getting started initial state def init(_) do data = %{}

    {:ok, :off, data} end def start_link(_opts) do GenStateMachine.start_link(!__MODULE!__, []) end
  2. adventure 1: handle_event_function “event centered approach” branch on event then

    state all events handled in function handle_event/4 default callback mode
  3. choose your adventure use GenStateMachine, callback_mode: :state_functions callback_mode() !-> state_functions.

    use GenStateMachine, callback_mode: :handle_event_function callback_mode() !-> handle_event_function.
  4. state enter callbacks use GenStateMachine, callback_mode: [:state_functions, :state_enter] def off(:enter,

    :on, data) do # !!... :keep_state_and_data end event content: old state
  5. emulate selective receive The gen_statem event queue model is sufficient

    to emulate the normal process message queue with selective receive. Postponing an event corresponds to not matching it in a receive statement, and changing states corresponds to entering a new receive statement.
  6. emulate selective receive def wait_for_it do receive do {:ok, {:step,

    1}} !-> # !!... Do some stuff wait_for_it() after 0 !-> wait_for_it() end end
  7. state timeout in practice def handle_event( :state_timeout, {:response_timeout, stream, from},

    :awaiting_response, data ) do # Do some cleanup stuff!!... actions = {:reply, from, {:error, :response_timeout}} {:next_state, :ready, data, actions} end
  8. welcome to the machine def flip_it() do GenStateMachine.cast(!__MODULE!__, :flip) end

    def call_it() do GenStateMachine.call(!__MODULE!__, :hello) end