defmodule Circlex.Emulator.Notifier do
@moduledoc """
Process to handle sending out notifications, such as SNS subscriptions.
"""
use GenServer
require Logger
alias Circlex.Emulator.SNS
alias Circlex.Emulator.SNS.Notification
alias Circlex.Emulator.State.{PaymentState, PayoutState, SubscriptionState, TransferState}
alias Circlex.Struct.{Payment, Payout, Transfer}
def start_link(opts \\ []) do
listeners = Keyword.get(opts, :listeners, [])
GenServer.start_link(__MODULE__, %{state_pid: Process.get(:state_pid), listeners: listeners},
name: __MODULE__
)
end
@impl true
def init(%{state_pid: state_pid, listeners: listeners}) do
Process.put(:state_pid, state_pid)
{:ok, %{listeners: listeners}}
end
def notify_payout(payout_id, name \\ __MODULE__) when is_binary(payout_id) do
{:ok, payout} = PayoutState.get_payout(payout_id)
notification =
Notification.new(%{
clientId: "c60d2d5b-203c-45bb-9f6e-93641d40a599",
notificationType: "payouts",
version: 1,
payout: Payout.serialize(payout)
})
GenServer.cast(name, {:notify, notification})
end
def notify_payment(payment_id, name \\ __MODULE__) when is_binary(payment_id) do
{:ok, payment} = PaymentState.get_payment(payment_id)
notification =
Notification.new(%{
clientId: "c60d2d5b-203c-45bb-9f6e-93641d40a599",
notificationType: "payments",
version: 1,
payment: Payment.serialize(payment)
})
GenServer.cast(name, {:notify, notification})
end
def notify_transfer(transfer_id, name \\ __MODULE__) when is_binary(transfer_id) do
{:ok, transfer} = TransferState.get_transfer(transfer_id)
notification =
Notification.new(%{
clientId: "c60d2d5b-203c-45bb-9f6e-93641d40a599",
notificationType: "transfers",
version: 1,
transfer: Transfer.serialize(transfer)
})
GenServer.cast(name, {:notify, notification})
end
@impl true
def handle_cast({:notify, notification}, state = %{listeners: listeners}) do
# First, send notification to anything in notification state
for subscription <- SubscriptionState.all_subscriptions() do
Logger.info("Sending `#{notification.message.notificationType}` Notification")
SNS.send_message(subscription.endpoint, notification)
end
# Also, send to any registered listeners
for listener <- listeners do
case listener do
pid when is_pid(listener) or is_atom(pid) ->
send(listener, {:notify, notification})
f when is_function(f) ->
f.(notification)
{mod, fun, args} ->
apply(mod, fun, [notification | args])
end
end
{:noreply, state}
end
end