Current section
Files
Jump to
Current section
Files
lib/events/event_handler.ex
defmodule ElixirTools.Events.EventHandler do
alias ElixirTools.Events.{Event, NotSentEvent}
@type events_opt ::
{:event_handler_module, module}
| {:task_supervisor_module, module}
| {:event_module, module}
| {:not_sent_event_module, module}
| {:telemetry_module, module}
@typep event_schema :: map
@callback send_event(any, [events_opt]) :: :ok
@callback create(event_name, payload) :: Event.t()
@callback publish(Event.t(), [events_opt]) :: :ok
@callback publish(Event.t(), event_schema, [events_opt]) :: :ok
@optional_callbacks send_event: 2,
create: 2,
publish: 2,
publish: 3
@typep event_name :: String.t()
@typep payload :: map
@typep event_id_seed :: Ecto.UUID.t()
@spec create(event_name, payload, event_id_seed) :: Event.t()
def create(event_name, payload, event_id_seed) do
%Event{name: event_name, payload: payload, event_id_seed: event_id_seed}
end
@typep create_optional ::
{:event_id_seed_optional, String.t()}
| {:occurred_at, DateTime.t()}
| {:version, String.t()}
@spec create(event_name, payload, event_id_seed, [create_optional]) :: Event.t()
def create(event_name, payload, event_id_seed, create_optional) do
event_id_seed_optional = create_optional[:event_id_seed_optional] || ""
occurred_at = create_optional[:occurred_at]
version = create_optional[:version] || "1.0.0"
%Event{
name: event_name,
payload: payload,
event_id_seed: event_id_seed,
event_id_seed_optional: event_id_seed_optional,
occurred_at: occurred_at,
version: version
}
end
@spec publish(Event.t(), [events_opt]) :: :ok
def publish(event, opts) do
task_supervisor_module = opts[:task_supervisor_module] || Task.Supervisor
task_supervisor_module.async_nolink(ElixirTools.TaskSupervisor, fn ->
publish_event_call(event, opts)
end)
:ok
end
@spec publish(Event.t(), event_schema, [events_opt]) :: :ok
def publish(event, schema, opts) do
task_supervisor_module = opts[:task_supervisor_module] || Task.Supervisor
task_supervisor_module.async_nolink(ElixirTools.TaskSupervisor, fn ->
publish_event_call(event, schema, opts)
end)
:ok
end
@spec publish_event_call(Event.t(), [events_opt]) :: :ok | :error
def publish_event_call(event, opts) do
event_module = opts[:event_module] || Event
case event_module.publish_deprecated(event) do
{:error, reason} -> handle_error(event, reason, opts)
_ -> :ok
end
end
@spec publish_event_call(Event.t(), event_schema, [events_opt]) :: :ok | :error
def publish_event_call(event, schema, opts) do
event_module = opts[:event_module] || Event
case event_module.publish(event, schema) do
{:error, reason} -> handle_error(event, reason, opts)
_ -> :ok
end
end
@spec handle_error(Event.t(), String.t(), [events_opt]) :: :error
defp handle_error(event, error_reason, opts) do
telemetry_module = opts[:telemetry_module] || :telemetry
not_sent_event_module = opts[:not_sent_event_module] || NotSentEvent
error_info = event |> Map.from_struct() |> Map.put(:reason, inspect(error_reason))
telemetry_module.execute(
[:pagantis_elixir_tools, :events, :not_sent],
%{error_info: error_info}
)
not_sent_event_module.create!(%{content: Jason.encode!(error_info)})
:error
end
end