defmodule RegHelper do @moduledoc """ Helps with Registry related tasks... """ import Logger, only: [debug: 1, error: 1, info: 1, warn: 1] @mod __MODULE__ defmacro __using__ _options do quote do: import unquote @mod end defmacro name do quote do __MODULE__ |> to_string |> String.split(".") |> List.last |> String.to_atom end end defmacro reg_name do quote do Application.get_env Mix.Project.config[:app], :registry, :REGISTRY end end defmacro key id do quote do: {name(), unquote id} end defmacro via id do quote do: {:via, Registry, {reg_name(), key unquote id}} end defmacro lookup id do quote do case Process.whereis unquote id do pid when is_pid pid -> pid nil -> do_lookup unquote id end end end defmacro do_lookup id do quote do case Registry.lookup reg_name(), key unquote id do [{pid, nil}] -> pid [] -> :undefined end end end defmacro restore id do quote do: Registry.meta reg_name(), key unquote id end defmacro store id, state do quote do: Registry.put_meta reg_name(), key(unquote id), unquote state end @spec log_start(GenServer.on_start) :: GenServer.on_start def log_start on_start do case on_start do {:ok, pid} -> debug reveal pid, "started ok" :ignore -> error "failed to start: :ignore" {:error, {:already_started, pid}} -> warn reveal pid, "already started" {:error, reason} -> error "failed to start: #{inspect reason}" end on_start end @spec reveal(pid, String.t) :: String.t defp reveal pid, tail do String.trim_trailing "#{tag pid} #{inspect pid} #{tail}" end @spec tag(pid) :: atom | String.t defp tag pid do case Process.info(pid)[:registered_name] do nil -> Registry.keys(reg_name(), pid) |> List.first |> inspect name -> name end end @spec log_init(String.t) :: :ok | {:error, term} def log_init(tail \\ ""), do: warn reveal self(), "starting #{tail}" @spec log_debug(pid, String.t) :: :ok | {:error, term} def log_debug(pid \\ self(), tail), do: debug reveal pid, tail @spec log_info(pid, String.t) :: :ok | {:error, term} def log_info(pid \\ self(), tail), do: info reveal pid, tail @spec log_warn(pid, String.t) :: :ok | {:error, term} def log_warn(pid \\ self(), tail), do: warn reveal pid, tail @spec log_error(pid, String.t) :: :ok | {:error, term} def log_error(pid \\ self(), tail), do: error reveal pid, tail end