Envío
Envío is basically a GenEvent², the modern idiomatic pub-sub
implementation of event passing.
In a nutshell, Envío is a set of handy tools to simplify dealing with Elixir
Registry. It includes
the instance of Registry to be used out of the box, scaffolds for
producing publishers and subscribers.
It is built using “convention over configuration” approach, preserving the whole low-level control over the registry entries.
Just add the application :envio into your list of extra applications
and the default Envio.Registry will be started and managed automagically.
def application do
[
mod: {MyApplication, []},
extra_applications: ~w|envio ...|a
]
end
Creating a publisher
To create a publisher just use Envio.Publisher in the module that should
publish messages to the subscribers. Once use Envio.Publisher is used,
broadcast/2 function becomes available. If the optional channel:
argument is passed to use Envio.Publisher, this channel is considered
the default one and broadcast/1 function appears to publish directly
to the default channel.
defmodule MyPub do
use Envio.Publisher, channel: :main
def publish(channel, what), do: broadcast(channel, what)
def publish(what), do: broadcast(what)
end
Creating a subscriber
▶ :dispatch
Simply register the handler anywhere in the code:
Envio.register(
{MySub, :on_envio}, # the function of arity 2 must exist
dispatch: %Envio.Channel{source: MyPub, name: :main}
)
As MyPub publishes to the :main channel, MySub.on_envio/2 will
be called with a message passed as parameter.
▶ :pub_sub
Use Envio.Subscriber helper to scaffold the registry subscriber. Implement
handle_envio/2 for custom message handling. The default implementation
collects last 10 messages in it’s state. This amount might be adjusted by
changing :envio, :subscriber_queue_size application environment setting.
The implementation below subscribes to :main channel provided by MyPub
publisher and prints out each subsequent incoming message to standard output.
defmodule PubSucker do
use Envio.Subscriber, channels: [{MyPub, :main}]
def handle_envio(message, state) do
{:noreply, state} = super(message, state)
IO.inspect({message, state}, label: "Received")
{:noreply, state}
end
end