Current section
Files
Jump to
Current section
Files
lib/event_bus.ex
defmodule PlanB.EventBus do
use GenServer
@moduledoc """
## Module EventBus
This module is created as a GenServer. To use it just call start_link/1, then create a channel and register subscribers to it.
"""
# Server side
@spec init(any) :: {:ok, any}
def init(state) do
{:ok, state}
end
def handle_call({:lookup, name}, _from, state) when is_binary(name) do
state
|> Map.fetch(name)
|> case do
:error -> {:reply, :fail, state}
{:ok, modules} ->
results =
modules
|> Enum.map(fn (module) -> {module, Process.whereis(module) } end)
{:reply, {name, results}, state}
end
end
def handle_call({:register, {name, module}}, _from, state) do
state
|> Map.fetch(name)
|> case do
:error ->
new_state = state |> Map.put(name, [ module ])
{:reply, :ok, new_state}
{:ok, modules} ->
modules
|> Enum.member?(module)
|> case do
true -> {:reply, :ok, state}
false ->
new_state = state |> Map.put(name, modules ++ [module])
{:reply, :ok, new_state}
end
end
end
def handle_cast({:publish, name, payload}, state) do
state
|> Map.fetch(name)
|> case do
:error -> {:noreply, state}
{:ok, modules} ->
modules
|> Enum.each(fn (module) -> GenServer.cast(module, payload) end)
{:noreply, state}
end
end
# Client side
@doc """
### start_link/1
"""
@spec start_link(any) :: :ignore | {:error, any} | {:ok, pid}
def start_link([state] = args) when is_list(args) and is_map(state) do
GenServer.start_link __MODULE__, state, name: __MODULE__
end
@doc """
### stop_server/0
"""
@spec stop_server :: :ok
def stop_server, do: GenServer.stop __MODULE__
@doc """
### health_check/0
"""
@spec health_check :: :fail | :ok
def health_check do
case GenServer.whereis(__MODULE__) do
pid when is_pid(pid) -> :ok
_ -> :fail
end
end
@doc """
### register/2
"""
@spec register(binary, Module) :: any
def register(name, module), do: GenServer.call __MODULE__, {:register, {name, module}}
@doc """
### lookup/1
"""
@spec lookup(binary) :: any
def lookup(name) when is_binary(name), do: GenServer.call __MODULE__, {:lookup, name}
@doc """
### publish/2
"""
@spec publish(binary, any) :: any
def publish(name, payload) when is_binary(name), do: GenServer.cast __MODULE__, {:publish, name, payload}
end