defmodule Ash.Notifier do @moduledoc """ A notifier is an extension that receives various events """ @callback notify(Ash.Notifier.Notification.t()) :: :ok defmacro __using__(_) do quote do @behaviour Ash.Notifier end end @doc """ Sends any notifications that can be sent, and returns the rest. A notification can only be sent if you are not currently in a transaction for the resource in question. """ @spec notify(list(Ash.Notifier.Notification.t()) | Ash.Notifier.Notification.t()) :: list(Ash.Notifier.Notification.t()) def notify(resource_notifications) do {unsent, to_send} = resource_notifications |> List.wrap() |> Enum.group_by(& &1.resource) |> Enum.split_with(fn {resource, _} -> resource && Ash.DataLayer.in_transaction?(resource) end) for {resource, notifications} <- to_send do for notification <- notifications do case notification.for do nil -> for notifier <- Ash.Resource.Info.notifiers(resource) do notifier.notify(notification) end allowed_notifiers -> for notifier <- List.wrap(allowed_notifiers) do notifier.notify(notification) end end end end unsent |> Enum.map(&elem(&1, 1)) |> List.flatten() end end