OTP GenServer

Minimal descriptive example of an OTP GenServer in Elixir.

defmodule Crawler.Explorer do
  use GenServer

  ## Client API

  @doc """
  Starts the process.
  """
  def start_link(opts) do
    GenServer.start_link(__MODULE__, :ok, opts)
  end

  @doc """
  execute a synchronous call to get data from the server
  """
  def lookup(server, name) do
    GenServer.call(server, {:lookup, name})
  end

  @doc """
  dispatch an asynchronous call to the server, will not wait for any response
  """
  def create(server, name) do
    GenServer.cast(server, {:create, name})
  end

  ## Server Callbacks

  @doc """
  Will be called from `GenServer.start_link/1`
  """
  def init(:ok) do
    initial_data = %{}
    {:ok, initial_data}
  end

  @doc """
  The Client will wait blocked until the call succeeds, applying backpressure
  """
  def handle_call({:lookup, name}, _from, data) do
    {:reply, Map.fetch(data, name), data}
  end

  @doc """
  The Client will **not** wait until the call succeeds, fire-and-forget
  """
  def handle_cast({:create, name}, data) do
    if Map.has_key?(data, name) do
      {:noreply, data}
    else
      {:noreply, Map.put(data, name, "new value")}
    end
  end
end

Implements a simple Map lookup with the common functions and callbacks. Should always be started from an OTP Supervisor.

Technologies: