Skip to content

Commit

Permalink
feat: add detour notifications to notifications server
Browse files Browse the repository at this point in the history
fix: set name to __MODULE__
  • Loading branch information
firestack committed Sep 26, 2024
1 parent 91773c9 commit 64d4d59
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 1 deletion.
65 changes: 65 additions & 0 deletions lib/notifications/notification_server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,29 @@ defmodule Notifications.NotificationServer do
GenServer.cast(server, {:bridge_movement, bridge_movement})
end

@doc """
Creates a new Detour Activated Notification for a `Skate.Detours.Db.Detour`.
## Options
If the `:server` option is present, the notification is sent to the process
referred to by the `:server` value.
If the `:notify_finished` option is present, a `{:new_notification, detour: detour.id}` message
is sent to the process referred to by the `:notify_finished` value.
"""
@spec detour_activated(detour :: Skate.Detours.Db.Detour.t()) :: :ok
@spec detour_activated(detour :: Skate.Detours.Db.Detour.t(), keyword()) :: :ok
def detour_activated(
%Skate.Detours.Db.Detour{} = detour,
options \\ []
) do
server = Keyword.get(options, :server, default_name())
notify_finished = Keyword.get(options, :notify_finished, nil)

GenServer.cast(server, {:detour_activated, detour, notify_finished})
end

def subscribe(user_id, server \\ default_name()) do
registry_key = GenServer.call(server, :subscribe)

Expand Down Expand Up @@ -70,6 +93,33 @@ defmodule Notifications.NotificationServer do
{:noreply, state}
end

@impl true
def handle_cast(
{
:detour_activated,
%Skate.Detours.Db.Detour{id: id} = detour,
notify_finished_caller_id
},
state
) do
detour
|> Notifications.Notification.create_activated_detour_notification_from_detour()
|> broadcast(self())

notify_caller_new_notification(notify_finished_caller_id, detour: id)

{:noreply, state}
end

# Tell the caller when a notification is created
# Mainly useful for writing tests so that they don't require
# `Process.sleep(<N>)`
defp notify_caller_new_notification(nil = _caller_id, _value), do: nil

defp notify_caller_new_notification(caller_id, value) do
send(caller_id, {:new_notification, value})
end

@spec convert_new_block_waivers_to_notifications([BlockWaiver.t()]) :: [
Notification.t()
]
Expand Down Expand Up @@ -198,6 +248,21 @@ defmodule Notifications.NotificationServer do
broadcast(notification, User.user_ids_for_route_ids(@chelsea_bridge_route_ids), registry_key)
end

defp broadcast(
%Notifications.Notification{
content: %Notifications.Db.Detour{}
} = notification,
registry_key
) do
n = {:notification, default_unread(notification)}

Registry.dispatch(Notifications.Supervisor.registry_name(), registry_key, fn entries ->
for {pid, _user_id} <- entries do
send(pid, n)
end
end)
end

defp broadcast(
%Notifications.Notification{
content: %Notifications.Db.BlockWaiver{
Expand Down
53 changes: 52 additions & 1 deletion test/notifications/notification_server_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ defmodule Notifications.NotificationServerTest do
start_supervised({Registry, keys: :duplicate, name: registry_name})
reassign_env(:notifications, :registry, registry_name)

{:ok, server} = NotificationServer.start_link(name: :new_notifications)
{:ok, server} = NotificationServer.start_link(name: __MODULE__)

if user_id do
NotificationServer.subscribe(user_id, server)
Expand Down Expand Up @@ -613,4 +613,55 @@ defmodule Notifications.NotificationServerTest do
refute String.contains?(log, "new_notification")
end
end

# rename to activated_detour?
describe "detour_activated/3" do
setup do
{:ok, server} = setup_server()

%{server: server}
end

test "saves to database" do
notification_count = 3
# create new notification
for _ <- 1..notification_count do
%{id: id} =
detour =
insert(:detour)

NotificationServer.detour_activated(detour, notify_finished: self(), server: __MODULE__)

assert_receive {:new_notification, detour: ^id}
end

# assert database contains notification
assert_n_notifications_in_db(notification_count)
end

test "broadcasts to all connected users", %{server: server} do
notification_count = 3
# connect users to channel
for id <- 1..notification_count do
NotificationServer.subscribe(id, server)
end

# create new notification
%{id: id} =
detour =
insert(:detour)

NotificationServer.detour_activated(detour, notify_finished: self(), server: __MODULE__)

assert_receive {:new_notification, detour: ^id}

# assert channel sends notifications to each user
for _ <- 1..notification_count do
assert_receive {:notification,
%Notification{
content: %Notifications.Db.Detour{}
}}
end
end
end
end

0 comments on commit 64d4d59

Please sign in to comment.