Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Elixir School - Advanced

elixir_school_advanced.livemd

Elixir School - Advanced

OTP Concurrency

GenServer

A module that implements a GenServer behaviour is an OTP Server

To implement the GenServer behaviour add this contract via the use macro

GenServer‘s can have both sync and async functions to handle requests

sync: GenServer.handle_call/3

async: GenServer.handle_cast/3

defmodule SimpleQueue do
  use GenServer

  @doc """
  Start our queue and link it.
  This is a helper function
  """
  def start_link(state \\ []) do
    GenServer.start_link(__MODULE__, state, name: __MODULE__)
  end

  @doc """
  GenServer.init/1 callback
  """
  def init(state), do: {:ok, state}

  def handle_call(:dequeue, _from, [value | state]) do
    {:reply, value, state}
  end

  def handle_call(:dequeue, _from, []) do
    {:reply, nil, []}
  end

  def handle_call(:queue, _from, state) do
    {:reply, state, state}
  end

  @doc """
  GenServer.handle_cast/2 callback
  """
  def handle_cast({:enqueue, value}, state) do
    {:noreply, state ++ [value]}
  end

  def queue, do: GenServer.call(__MODULE__, :queue)
  def enqueue(value), do: GenServer.cast(__MODULE__, {:enqueue, value})
  def dequeue, do: GenServer.call(__MODULE__, :dequeue)
end

State the queue server

# {:ok, sqpid} = SimpleQueue.start_link([1, 2, 3])

Remove the next number from the queue

# SimpleQueue.dequeue()

Inspect the current queue

# SimpleQueue.queue()

Add a number to the queue

# SimpleQueue.enqueue(3)

Kill server

# Process.exit(sqpid, :kill)

OTP Supervisors

Supervisors are specialize processes that montior other processes

Enables fault tolerant programming through child process restart on failure

{:ok, app_pid} =
  Supervisor.start_link(
    [{SimpleQueue, [1, 2, 3]}],
    strategy: :one_for_one,
    name: SimpleQueue.Supervisor
  )
# SimpleQueue.queue
# Process.exit(app_pid, :kill)