Current section
Files
Jump to
Current section
Files
lib/boltun.ex
defmodule Boltun do
@moduledoc """
Provides macros to define a listener and its callbacks. See the example below
defmodule TestListener do
use Boltun, otp_app: :my_app
listen do
channel "my_channel", :my_callback
channel "my_channel", :my_other_callback
channel "my_other_channel", :my_other_callback
end
def my_callback(channel, payload) do
IO.puts channel
IO.puts payload
end
...
end
"""
defmacro __using__(opts) do
otp_app = Keyword.fetch!(opts, :otp_app)
quote do
import Boltun, only: [channel: 2, channel: 3, channel: 4, listen: 1]
Module.register_attribute(__MODULE__, :registered_callbacks, [])
Module.put_attribute(__MODULE__, :registered_callbacks, %{})
def config() do
Boltun.get_config(unquote(otp_app), __MODULE__)
end
end
end
@doc """
Defines a callback for the given channel, module, function and arguments.
"""
defmacro channel(channel, module, function, args) do
quote do
callback = {unquote(module), unquote(function), unquote(args)}
channel_cbs = Dict.get(@registered_callbacks, unquote(channel), []) ++ [callback]
Module.put_attribute(__MODULE__, :registered_callbacks, Dict.put(@registered_callbacks, unquote(channel), channel_cbs))
end
end
@doc """
Defines a callback for the given channel, function and optional arguments.
The callback must be defined in the same module using this macro.
"""
defmacro channel(channel, function, args \\ []) do
quote do
channel(unquote(channel), __MODULE__, unquote(function), unquote(args))
end
end
@doc """
Defines the listener and its callbacks. Multiple callbacks per channel are supported and they will be invoked in
in the order in which they appear in this block
"""
defmacro listen(do: source) do
quote do
unquote(source)
def start_link do
opts = [
connection: config(),
callbacks: @registered_callbacks, name: __MODULE__
]
Boltun.Supervisor.start_link(opts)
end
end
end
@doc false
def get_config(otp_app, module) do
if config = Application.get_env(otp_app, module) do
config
else
raise ArgumentError, "configuration for #{inspect module} not specified in #{inspect otp_app}"
end
end
end