diff --git a/lib/notifications/notification.ex b/lib/notifications/notification.ex index 8298bfd63..177527685 100644 --- a/lib/notifications/notification.ex +++ b/lib/notifications/notification.ex @@ -31,7 +31,10 @@ defmodule Notifications.Notification do id: id(), created_at: Util.Time.timestamp(), state: NotificationState.t(), - content: Notifications.Db.BlockWaiver.t() | Notifications.Db.BridgeMovement.t() + content: + Notifications.Db.BlockWaiver.t() + | Notifications.Db.BridgeMovement.t() + | Notifications.Db.Detour.t() } @derive Jason.Encoder diff --git a/lib/notifications/notification_server.ex b/lib/notifications/notification_server.ex index 0b30c01af..ab75f2f1d 100644 --- a/lib/notifications/notification_server.ex +++ b/lib/notifications/notification_server.ex @@ -102,11 +102,30 @@ defmodule Notifications.NotificationServer do }, state ) do - detour - |> Notifications.Notification.create_activated_detour_notification_from_detour() - |> broadcast(self()) + notification = + Notifications.Notification.create_activated_detour_notification_from_detour(detour) + + broadcast(notification, self()) notify_caller_new_notification(notify_finished_caller_id, detour: id) + broadcast_notification_to_other_instances(notification) + + {:noreply, state} + end + + @impl true + # "Private" method for fetching and sending notifications from distributed + # Elixir + def handle_cast( + { + :detour_activated_notification, + notification_id + }, + state + ) do + notification_id + |> Notifications.Notification.get_detour_notification() + |> broadcast(self()) {:noreply, state} end @@ -120,6 +139,37 @@ defmodule Notifications.NotificationServer do send(caller_id, {:new_notification, value}) end + defp broadcast_notification_to_other_instances( + %Notifications.Notification{ + id: notification_id, + content: %Notifications.Db.Detour{} + }, + options \\ [] + ) + when not is_nil(notification_id) do + # Currently, we've implemented our own "PubSub" for notifications and we + # are not using the provided `Phoenix.PubSub` that comes with Phoenix + # channels. This means we don't benefit from Phoenix PubSub's ability to + # send messages using distributed Elixir, and that we need to implement + # this ourselves at this current time. + # Ideally, Notifications would be delivered using + # `Phoenix.Channel.broadcast` instead of our custom `broadcast` function + # in `NotificationServer`. To do this, we'd need to implement the same + # filtering mechanism that this module has implemented. For now, we'll + # send messages to other Skate instances letting them know about new + # Notifications. + + # Skate instances currently do not "specialize", and therefore we need to + # send the notification to all instances + for node <- Node.list() do + Node.spawn(node, fn -> + server = Keyword.get(options, :server, default_name()) + + GenServer.cast(server, {:detour_activated_notification, notification_id}) + end) + end + end + @spec convert_new_block_waivers_to_notifications([BlockWaiver.t()]) :: [ Notification.t() ]