Current section

Files

Jump to
ravenx lib ravenx.ex
Raw

lib/ravenx.ex

defmodule Ravenx do
@moduledoc """
Ravenx main module.
It includes and manages dispatching of messages through registered strategies.
"""
@doc """
Dispatch a notification `payload` to a specified `strategy`.
Custom options for this call can be passed in `options` parameter.
Returns a tuple with `:ok` or `:error` indicating the final state.
## Examples
iex> Ravenx.dispatch(:slack, %{title: "Hello world!", body: "Science is cool"})
{:ok, "ok"}
iex> Ravenx.dispatch(:wadus, %{title: "Hello world!", body: "Science is cool"})
{:error, "wadus strategy not defined"}
"""
@spec dispatch(atom, map, map) :: {atom, any}
def dispatch(strategy, payload, options \\ %{}) do
handler = available_strategies
|> Keyword.get(strategy)
opts = get_options(strategy, payload, options)
unless (is_nil(handler)) do
Task.async(fn -> handler.call(payload, opts) end)
|> Task.await()
else
{:error, "#{strategy} strategy not defined"}
end
end
@doc """
Dispatch a notification `payload` to a specified `strategy` asynchronously.
Custom options for this call can be passed in `options` parameter.
Returns a tuple with `:ok` or `:error` indicating the task launch result.
If the result was `:ok`, the Task of the process launched is also returned
## Examples
iex> {status, task} = Ravenx.dispatch_async(:slack, %{title: "Hello world!", body: "Science is cool"})
{:ok, %Task{owner: #PID<0.165.0>, pid: #PID<0.183.0>, ref: #Reference<0.0.4.418>}}
iex> Task.await(task)
{:ok, "ok"}
iex> Ravenx.dispatch_async(:wadus, %{title: "Hello world!", body: "Science is cool"})
{:error, "wadus strategy not defined"}
"""
@spec dispatch_async(atom, map, map) :: {atom, any}
def dispatch_async(strategy, payload, options \\ %{}) do
handler = available_strategies
|> Keyword.get(strategy)
opts = get_options(strategy, payload, options)
unless (is_nil(handler)) do
task = Task.async(fn -> handler.call(payload, opts) end)
{:ok, task}
else
{:error, "#{strategy} specified not defined"}
end
end
@doc """
Function to get a Keyword list of registered strategies.
"""
@spec available_strategies() :: keyword
def available_strategies() do
[
slack: Ravenx.Strategy.Slack,
email: Ravenx.Strategy.Email
]
end
# Private function to get definitive options keyword list by getting options
# from three different places.
#
defp get_options(strategy, payload, options) do
# Get strategy configuration in application
app_config_opts = Application.get_env(:ravenx, strategy, %{})
# Get config module and call the function of this strategy (if any)
config_module_opts = Application.get_env(:ravenx, :config, nil)
|> call_config_module(strategy, payload)
# Merge options
app_config_opts
|> Map.merge(config_module_opts)
|> Map.merge(options)
end
# Private function to call the config module if it's defined.
#
defp call_config_module(module, _strategy, _payload) when is_nil(module), do: %{}
defp call_config_module(module, strategy, payload) do
if (Keyword.has_key?(module.__info__(:functions), strategy)) do
apply(module, strategy, [payload])
else
%{}
end
end
end