Skip to main content

lib/ping_pong/notification.ex

defmodule PingPong.Notification do
  @moduledoc """
  Normalizes notification tuples before dispatching.

  This module is used by `PingPong.send_multiple/1` and is also useful when a
  notification has already been represented as `{service, payload, options}`.
  It validates the tuple shape before delegating to `PingPong.send/3` or
  `PingPong.send_async/3`.
  """

  @doc """
  Sends a notification tuple with the requested delivery mode.

  Valid notifications are three-element tuples:

      {service, payload, options}

  The `service` must be an atom, and both `payload` and `options` must be maps.

  ## Examples

      iex> PingPong.Notification.send_notification({:mock, %{message: "Ping!"}, %{}}, :sync)
      {:ok, "Pong! 🏓"}

      iex> PingPong.Notification.send_notification([:mock], :sync)
      {:error, {:missing, :payload}}

  """
  @spec send_notification(PingPong.config(), PingPong.send_type()) :: PingPong.result()
  def send_notification(notification, send_type) do
    sender = get_sender(send_type)

    case notification do
      {service, payload, options}
      when is_atom(service) and is_map(payload) and is_map(options) ->
        sender.(service, payload, options)

      [_] ->
        {:error, {:missing, :payload}}

      _ ->
        {:error, {:invalid, :notification}}
    end
  end

  defp get_sender(:sync), do: &PingPong.send/3
  defp get_sender(:async), do: &PingPong.send_async/3
end