Packages

Brook provides an event stream client interface for distributed applications. Brook sends and receives messages with the event stream via a driver module and persists an application-specific view of the event stream via a storage module.

Current section

Files

Jump to
brook_stream lib brook dispatcher.ex
Raw

lib/brook/dispatcher.ex

defmodule Brook.Dispatcher do
@moduledoc """
Defines the Brook Dispatcher behaviour, requiring the
`init/0` and `dispatch/1` functions be implemented by
the client.
"""
@doc """
Start a Brook dispatcher.
"""
@callback init(instance: Brook.instance()) :: :ok
@doc """
Distributes received messages across multiple nodes.
"""
@callback dispatch(Brook.instance(), Brook.Event.t()) :: :ok
end
defmodule Brook.Dispatcher.Default do
@moduledoc """
Default implementation for the Brook.Dispatcher
Creates and joins a process group named `:brook_servers`.
Ensures all members of the process group receive notification
of the received event by a member of the group.
"""
import Brook.Config, only: [registry: 1]
@behaviour Brook.Dispatcher
@doc """
Creates and joins the Brook server to the process group
named `:brook_servers`.
"""
@impl Brook.Dispatcher
def init(args) do
instance = Keyword.fetch!(args, :instance)
{:ok, pid} = Supervisor.start_link(children(), strategy: :one_for_one, name: instance)
:pg.join(instance, pid)
end
defp children, do: [pg_spec()]
defp pg_spec do
%{
id: :pg,
start: {:pg, :start_link, []}
}
end
@doc """
Takes an event struct and forwards the event on to other
member nodes of the `:brook_servers` process group after
tagging the forwarded status of the event to `true`.
"""
@impl Brook.Dispatcher
def dispatch(instance, %Brook.Event{} = event) do
forwarded_event = %{event | forwarded: true}
(:pg.get_members(instance) -- :pg.get_local_members(instance))
|> Enum.each(fn pid ->
GenServer.cast(pid, {:process, forwarded_event})
end)
end
end
defmodule Brook.Dispatcher.Noop do
@behaviour Brook.Dispatcher
def init(_args) do
:ok
end
def dispatch(_instance, _event) do
:ok
end
end