Packages

Rentbrella's aws' SQS' package.

Current section

Files

Jump to
lib_elixir_eventbus lib pub event_bus event.ex
Raw

lib/pub/event_bus/event.ex

defmodule Pub.Event do
@moduledoc "Represents a Event"
@derive Jason.Encoder
defstruct [:payload, :event]
@type t :: %__MODULE__{
payload: map(),
event: binary()
}
alias __MODULE__
alias Pub.EventSpec
@doc """
Creates new Event's struct
### Examples
iex> Pub.Event.new("event1", %{"user_id" => 1})
{:ok,
%Pub.Event{
event: "event1",
payload: %{user_id: 1}
}}
"""
@spec new(binary(), map()) :: {:ok, t()} | {:error, atom, list}
def new(event_name, %{} = payload) when is_binary(event_name) do
%Event{}
|> Map.put(:event, event_name)
|> Map.put(:payload, payload)
|> validate_and_transform()
end
defp validate_and_transform(%{event: event_name} = event) do
case EventSpec.get(event_name) do
{:error, reason} ->
{:error, reason}
{:ok, spec_fields} ->
event
|> compare_payload_with_spec(spec_fields)
end
end
defp compare_payload_with_spec(%{payload: payload} = event, spec_fields) do
case compare_field_lists(payload, spec_fields) do
[] ->
case compare_field_lists(spec_fields, payload) do
[] ->
payload =
payload
|> Enum.reduce(%{}, fn {key, value}, acc ->
key =
if is_atom(key) do
key
else
String.to_existing_atom(key)
end
Map.put(acc, key, value)
end)
{:ok, Map.put(event, :payload, payload)}
fields ->
{:error, {:missing_fields, fields}}
end
fields ->
{:error, {:surplus_fields, fields}}
end
end
defp compare_field_lists(%{} = left, right),
do: compare_field_lists(Map.keys(left), right)
defp compare_field_lists(left, %{} = right),
do: compare_field_lists(left, Map.keys(right))
defp compare_field_lists(left, right) do
left = atom_fields_to_string(left)
right = atom_fields_to_string(right)
left -- right
end
defp atom_fields_to_string(fields) do
fields
|> Enum.map(fn field ->
if is_atom(field) do
Atom.to_string(field)
else
field
end
end)
end
end