Skip to content

Instantly share code, notes, and snippets.

@amokan
Last active July 21, 2022 11:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amokan/a9d63786fbed7a215030f11a8e93aab7 to your computer and use it in GitHub Desktop.
Save amokan/a9d63786fbed7a215030f11a8e93aab7 to your computer and use it in GitHub Desktop.
Comparison of GenServer state orchestration using send/2 vs the new handle_continue callback
defmodule GroceryCart do
@moduledoc """
Simple example showing the `handle_continue` callback in Erlang/OTP 21+
"""
use GenServer
# simple contrived struct for state - didn't need to be a struct at all
defstruct items: []
@doc """
Start a new instance of the Grocery Cart server
"""
def start_link, do: GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
@doc false
def init(_) do
{:ok, %__MODULE__{}, {:continue, :add_cheese}}
end
@doc false
def handle_continue(:add_cheese, %__MODULE__{items: items} = state) do
updated_state = %__MODULE__{state | items: ["cheese" | items]}
{:noreply, updated_state, {:continue, :add_milk}}
end
@doc false
def handle_continue(:add_milk, %__MODULE__{items: items} = state) do
updated_state = %__MODULE__{state | items: ["milk" | items]}
{:noreply, updated_state, {:continue, :print_and_exit}}
end
@doc false
def handle_continue(:print_and_exit, %__MODULE__{items: items} = state) do
IO.inspect(items, label: "Items")
IO.puts("Will Exit Now")
{:stop, :normal, state}
end
end
defmodule GroceryCartOld do
@moduledoc """
Simple example showing how to orchestrate a GenServer progressing it's own state
"""
use GenServer
# simple contrived struct for state - didn't need to be a struct at all
defstruct items: []
@doc """
Start a new instance of the Grocery Cart server
"""
def start_link, do: GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
@doc false
def init(_) do
# queues up a msg to itself using `send()` which will be picked up by a `handle_info/2` callback
send(self(), :add_cheese)
{:ok, %__MODULE__{}}
end
@doc false
def handle_info(:add_cheese, %__MODULE__{items: items} = state) do
updated_state = %__MODULE__{state | items: ["cheese" | items]}
# queues up a msg to itself using `send()` which will be picked up by a `handle_info/2` callback
send(self(), :add_milk)
{:noreply, updated_state}
end
@doc false
def handle_info(:add_milk, %__MODULE__{items: items} = state) do
updated_state = %__MODULE__{state | items: ["milk" | items]}
# queues up a msg to itself using `Process.send_after()` with a delay of 1 second - this will be picked up by a `handle_info/2` callback
Process.send_after(self(), :print_and_exit, 1_000)
{:noreply, updated_state}
end
@doc false
def handle_info(:print_and_exit, %__MODULE__{items: items} = state) do
IO.inspect(items, label: "Items")
IO.puts("Will Exit Now")
{:stop, :normal, state}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment