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

gen_statem - OTP's Unsung Hero

gen_statem - OTP's Unsung Hero

Given at AlchemyConf 2025 in Braga, Portugal.

Avatar for Andrea Leopardi

Andrea Leopardi

April 04, 2025
Tweet

More Decks by Andrea Leopardi

Other Decks in Programming

Transcript

  1. FSM

  2. def accepting_coins( {:call, from}, {:press_button, beverage}, data ) do if

    enough_credit?(data, beverage) do dispense_beverage(data, beverage) actions = [{:reply, from, :ok}] {:next_state, :dispensing, data, actions} else # ... end end
  3. def dispensing(:cast, {:add_coin, _}, data) do actions = [:postpone] {:keep_state_and_data,

    actions} end def accepting_coins(:cast, {:add_coin, _}, data) do # Normal implementation end
  4. def accepting_coins(:cast, {:put_coin, coin}, data) do actions = [ {:timeout,

    to_timeout(second: 30), :give_back_coins} ] {:keep_state, update_in(data.credit, &add_coin/1), actions} end def accepting_coins(:timeout, :give_back_coins, data)
  5. def dispensing(:enter, _old_state, _data) do actions = [ {:state_timeout, to_timeout(minute:

    1), :stuck} ] {:keep_state_and_data, actions} end def dispensing(:state_timeout, :stuck, data) do # Call for help, the machine got stuck. end
  6. def init(options) do actions = [ {{:timeout, :self_health_check}, to_timeout(hour: 1),

    :no_content} ] {:ok, :idle, data, actions} end def idle({:timeout, :self_health_check}, _content, data) do # ... end
  7. def accepting_coins({:timeout, :self_health_check}, _, _) do {:keep_state_and_data, [:postpone]} end def

    dispensing({:timeout, :self_health_check}, _, _) do {:keep_state_and_data, [:postpone]} end
  8. def handle_event( :cast, {:put_coin, coin}, {:accepting_coins, credit}, data ) do

    new_state = {:accepting_coins, credit + coin} {:next_state, new_state, data} end