Antenna (antenna v0.2.1)
View SourceAntenna
is a mixture of Phoenix.PubSub
and :gen_event
functionality
with some batteries included.
It implements back-pressure on top of GenStage
, is fully conformant with
OTP Design Principles. and
is distributed out of the box.
Antenna
supports both asynchronous and synchronous events. While the most preferrable way
would be to stay fully async with Antenna.event/3
, one still might propagate the event
synchronously with Antenna.sync_event/3
and collect all the responses from all the handlers.
One can have as many isolated Antenna
s as necessary, distinguished by Antenna.t:id/0
.
The workflow looks like shown below.
Sequence Diagram
sequenceDiagram
Consumer->>+Broadcaster: sync_event(channel, event)
Consumer->>+Broadcaster: event(channel, event)
Broadcaster-->>+Consumer@Node1: event
Broadcaster-->>+Consumer@Node2: event
Broadcaster-->>+Consumer@NodeN: event
Consumer@Node1-->>-NoOp: mine?
Consumer@NodeN-->>-NoOp: mine?
Consumer@Node2-->>+Matchers: event
Matchers-->>+Handlers: handle_match/2
Matchers-->>+Handlers: handle_match/2
Handlers->>-Consumer: response(to: sync_event)
Usage Example
The consumer of this library is supposed to declare one or more matchers, subscribing to one
or more channels, and then call Antenna.event/2
to propagate the event.
assert {:ok, _pid, "{:tag_1, a, _} when is_nil(a)"} =
Antenna.match(Antenna, {:tag_1, a, _} when is_nil(a), self(), channels: [:chan_1])
assert :ok = Antenna.event(Antenna, [:chan_1], {:tag_1, nil, 42})
assert_receive {:antenna_event, :chan_1, {:tag_1, nil, 42}}
Summary
Functions (Client)
Sends an event to all the associated matchers through channels.
Sends an event to all the associated matchers through channels and collects results.
Functions (Setup)
Adds a handler to the matcher process specified by pid
Declares a matcher for tagged events.
Subscribes a matcher process specified by pid
to a channel(s)
Removes a handler from the matcher process specified by pid
Undeclares a matcher for tagged events previously declared with Antenna.match/4
.
Unsubscribes a previously subscribed matcher process specified by pid
from the channel(s)
Functions (Internals)
Returns a map of matches to matchers
Types
The identifier of the channel, messages can be sent to, preferrably atom()
The event being sent to the listeners
The actual handler to be associated with an event(s). It might be either a function or a process id, in which case the message of a following shape will be sent to it.
Functions (Client)
Sends an event to all the associated matchers through channels.
The special :*
might be specified as channels, then the event
will be sent to all the registered channels.
If one wants to collect results of all the registered event handlers,
they should look at sync_event/3
instead.
Sends an event to all the associated matchers through channels and collects results.
The special :*
might be specified as channels, then the event
will be sent to all the registered channels.
Unlike event/3
, this call is synchronous, which means it would block until
all the registered handlers respond; the results would have been collected
and returned as a list of no specific order.
Functions (Setup)
Adds a handler to the matcher process specified by pid
Declares a matcher for tagged events.
Example
Antenna.match(Antenna, %{tag: _, success: false}, fn channel, message ->
Logger.warning("The processing failed for [" <>
inspect(channel) <> "], result: " <> inspect(message))
end, channels: [:rabbit])
Subscribes a matcher process specified by pid
to a channel(s)
Removes a handler from the matcher process specified by pid
Undeclares a matcher for tagged events previously declared with Antenna.match/4
.
Accepts both an original match or a name returned by Antenna.match/4
,
which is effectively Macro.to_string(match)
.
Example
Antenna.unmatch(Antenna, %{tag: _, success: false})
Unsubscribes a previously subscribed matcher process specified by pid
from the channel(s)
Functions (Internals)
@spec registered_matchers(id :: id()) :: %{ required(term()) => {pid(), Supervisor.child_spec()} }
Returns a map of matches to matchers
Types
The identifier of the channel, messages can be sent to, preferrably atom()
@type event() :: term()
The event being sent to the listeners
@type handler() :: (event() -> term()) | (channel(), event() -> term()) | Antenna.Matcher.t() | pid() | GenServer.name()
The actual handler to be associated with an event(s). It might be either a function or a process id, in which case the message of a following shape will be sent to it.
{:antenna_event, channel, event}
@type id() :: module()
The identifier of the isolated Antenna