From c3be0aa6493383523b82314ecd4460845d137cc1 Mon Sep 17 00:00:00 2001 From: Brian Fauble Date: Tue, 11 Feb 2025 15:01:06 -0700 Subject: [PATCH 1/5] make use of status field in detour list queries --- lib/skate/detours/db/detour.ex | 4 ++ lib/skate/detours/detours.ex | 65 +++++++++++------------ lib/skate_web/channels/detours_channel.ex | 6 +-- 3 files changed, 37 insertions(+), 38 deletions(-) diff --git a/lib/skate/detours/db/detour.ex b/lib/skate/detours/db/detour.ex index d48d2345f..a11ffd240 100644 --- a/lib/skate/detours/db/detour.ex +++ b/lib/skate/detours/db/detour.ex @@ -154,6 +154,10 @@ defmodule Skate.Detours.Db.Detour do ) end + def with_virtual_fields(query \\ base()) do + select_virtual_fields(query, Skate.Detours.Db.Detour.__schema__(:virtual_fields)) + end + def select_detour_list_info(query \\ base()) do query |> select_fields([ diff --git a/lib/skate/detours/detours.ex b/lib/skate/detours/detours.ex index a16c7d821..4c4574482 100644 --- a/lib/skate/detours/detours.ex +++ b/lib/skate/detours/detours.ex @@ -40,11 +40,15 @@ defmodule Skate.Detours.Detours do [%Detour{}, ...] """ def active_detours_by_route(route_id) do - list_detours() + Skate.Detours.Db.Detour + |> from(as: :detour) + |> Skate.Detours.Db.Detour.Queries.with_virtual_fields() + |> where([detour: d], d.status == :active) + |> Repo.all() |> Enum.filter(fn detour -> - categorize_detour(detour) == :active and detour.route_id == route_id + detour.route_id == route_id end) - |> Enum.map(fn detour -> db_detour_to_detour(detour) end) + |> Enum.map(&db_detour_to_detour/1) end @doc """ @@ -65,34 +69,36 @@ defmodule Skate.Detours.Detours do past: list(DetailedDetour.t()) | nil } def grouped_detours(user_id) do - detours = - list_detours() - |> Enum.map(&db_detour_to_detour/1) - |> Enum.filter(& &1) - |> Enum.group_by(fn - %ActivatedDetourDetails{details: %{status: status}} -> status - %{status: status} -> status - end) - %{ - active: Map.get(detours, :active, []), - draft: - detours - |> Map.get(:draft, []) - |> Enum.filter(fn detour -> detour.author_id == user_id end), - past: Map.get(detours, :past, []) + active: detours_for_user(user_id, :active), + draft: detours_for_user(user_id, :draft), + past: detours_for_user(user_id, :past) } end - @spec db_detour_to_detour(Detour.t()) :: DetailedDetour.t() | nil - @spec db_detour_to_detour(status :: Detour.status(), Detour.t()) :: DetailedDetour.t() | nil - def db_detour_to_detour(%{} = db_detour) do - db_detour_to_detour(categorize_detour(db_detour), db_detour) + def detours_for_user(user_id, status) do + Skate.Detours.Db.Detour + |> from(as: :detour) + |> preload([:author]) + |> apply_user_and_status_filter(user_id, status) + |> order_by([detour: d], desc: d.updated_at) + |> Repo.all() + |> Enum.map(&db_detour_to_detour/1) + |> Enum.reject(&is_nil/1) + end + + defp apply_user_and_status_filter(query, user_id, :draft) do + where(query, [detour: d], d.status == :draft and d.author_id == ^user_id) + end + + defp apply_user_and_status_filter(query, _user_id, status) do + where(query, [detour: d], d.status == ^status) end + @spec db_detour_to_detour(Detour.t()) :: DetailedDetour.t() | ActivatedDetourDetails.t() | nil def db_detour_to_detour( - :active, %{ + status: :active, activated_at: activated_at, estimated_duration: estimated_duration } = db_detour @@ -107,21 +113,10 @@ defmodule Skate.Detours.Detours do } end - def db_detour_to_detour( - status, - %{} = db_detour - ) do + def db_detour_to_detour(%{status: status} = db_detour) do DetailedDetour.from(status, db_detour) end - def db_detour_to_detour(state, invalid_detour) do - Sentry.capture_message("Detour error: the detour has an outdated schema", - extra: %{error: invalid_detour, state: state} - ) - - nil - end - @doc """ Takes a `Skate.Detours.Db.Detour` struct and a `Skate.Settings.Db.User` id and returns a `t:Detour.status/0` based on the state of the detour. diff --git a/lib/skate_web/channels/detours_channel.ex b/lib/skate_web/channels/detours_channel.ex index 08d03fcc4..77d370899 100644 --- a/lib/skate_web/channels/detours_channel.ex +++ b/lib/skate_web/channels/detours_channel.ex @@ -11,7 +11,7 @@ defmodule SkateWeb.DetoursChannel do def join_authenticated("detours:active", _message, socket) do SkateWeb.Endpoint.subscribe("detours:active") %{id: user_id} = Guardian.Phoenix.Socket.current_resource(socket) - detours = Detours.grouped_detours(user_id)[:active] + detours = Detours.detours_for_user(user_id, :active) {:ok, %{data: detours}, socket} end @@ -27,7 +27,7 @@ defmodule SkateWeb.DetoursChannel do def join_authenticated("detours:past", _message, socket) do SkateWeb.Endpoint.subscribe("detours:past") %{id: user_id} = Guardian.Phoenix.Socket.current_resource(socket) - detours = Detours.grouped_detours(user_id)[:past] + detours = Detours.detours_for_user(user_id, :past) {:ok, %{data: detours}, socket} end @@ -36,7 +36,7 @@ defmodule SkateWeb.DetoursChannel do def join_authenticated("detours:draft:" <> author_uuid, _message, socket) do SkateWeb.Endpoint.subscribe("detours:draft:" <> author_uuid) %{id: user_id} = Guardian.Phoenix.Socket.current_resource(socket) - detours = Detours.grouped_detours(user_id)[:draft] + detours = Detours.detours_for_user(user_id, :draft) {:ok, %{data: detours}, socket} end From 5688383b789a0fc634450790a555bb463d89c2f5 Mon Sep 17 00:00:00 2001 From: Brian Fauble Date: Tue, 11 Feb 2025 15:08:09 -0700 Subject: [PATCH 2/5] use select_detour_list_info --- lib/skate/detours/db/detour.ex | 1 + lib/skate/detours/detours.ex | 9 ++------- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/skate/detours/db/detour.ex b/lib/skate/detours/db/detour.ex index a11ffd240..567c410bd 100644 --- a/lib/skate/detours/db/detour.ex +++ b/lib/skate/detours/db/detour.ex @@ -166,6 +166,7 @@ defmodule Skate.Detours.Db.Detour do :author_id, :activated_at, :updated_at, + :status, # Virtual Fields :route_id, diff --git a/lib/skate/detours/detours.ex b/lib/skate/detours/detours.ex index 4c4574482..5e1925d14 100644 --- a/lib/skate/detours/detours.ex +++ b/lib/skate/detours/detours.ex @@ -40,9 +40,7 @@ defmodule Skate.Detours.Detours do [%Detour{}, ...] """ def active_detours_by_route(route_id) do - Skate.Detours.Db.Detour - |> from(as: :detour) - |> Skate.Detours.Db.Detour.Queries.with_virtual_fields() + Skate.Detours.Db.Detour.Queries.select_detour_list_info() |> where([detour: d], d.status == :active) |> Repo.all() |> Enum.filter(fn detour -> @@ -77,11 +75,8 @@ defmodule Skate.Detours.Detours do end def detours_for_user(user_id, status) do - Skate.Detours.Db.Detour - |> from(as: :detour) - |> preload([:author]) + Skate.Detours.Db.Detour.Queries.select_detour_list_info() |> apply_user_and_status_filter(user_id, status) - |> order_by([detour: d], desc: d.updated_at) |> Repo.all() |> Enum.map(&db_detour_to_detour/1) |> Enum.reject(&is_nil/1) From 5384caaf5aae23642c38f76edfdcdd9982dc8d84 Mon Sep 17 00:00:00 2001 From: Brian Fauble Date: Tue, 11 Feb 2025 15:16:43 -0700 Subject: [PATCH 3/5] remove unused func --- lib/skate/detours/db/detour.ex | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/skate/detours/db/detour.ex b/lib/skate/detours/db/detour.ex index 567c410bd..566ce0ca0 100644 --- a/lib/skate/detours/db/detour.ex +++ b/lib/skate/detours/db/detour.ex @@ -154,10 +154,6 @@ defmodule Skate.Detours.Db.Detour do ) end - def with_virtual_fields(query \\ base()) do - select_virtual_fields(query, Skate.Detours.Db.Detour.__schema__(:virtual_fields)) - end - def select_detour_list_info(query \\ base()) do query |> select_fields([ From 8040908c712eb2cc8af88d69bcda3facf1cc3da4 Mon Sep 17 00:00:00 2001 From: Brian Fauble Date: Tue, 18 Feb 2025 08:54:56 -0700 Subject: [PATCH 4/5] move grouping of detours into controller --- lib/skate/detours/detours.ex | 25 ------------------- .../controllers/detours_controller.ex | 6 ++++- 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/lib/skate/detours/detours.ex b/lib/skate/detours/detours.ex index 5e1925d14..dc4f5e642 100644 --- a/lib/skate/detours/detours.ex +++ b/lib/skate/detours/detours.ex @@ -49,31 +49,6 @@ defmodule Skate.Detours.Detours do |> Enum.map(&db_detour_to_detour/1) end - @doc """ - Returns the detours grouped by active, draft, and past. - - ## Examples - - iex> grouped_detours(my_user_id) - %{ - active: [%DetailedDetour{}, ...], - draft: nil, - past: [%DetailedDetour{}, ...] - } - """ - @spec grouped_detours(integer()) :: %{ - active: list(DetailedDetour.t()) | nil, - draft: list(DetailedDetour.t()) | nil, - past: list(DetailedDetour.t()) | nil - } - def grouped_detours(user_id) do - %{ - active: detours_for_user(user_id, :active), - draft: detours_for_user(user_id, :draft), - past: detours_for_user(user_id, :past) - } - end - def detours_for_user(user_id, status) do Skate.Detours.Db.Detour.Queries.select_detour_list_info() |> apply_user_and_status_filter(user_id, status) diff --git a/lib/skate_web/controllers/detours_controller.ex b/lib/skate_web/controllers/detours_controller.ex index 1c3abece7..329ee3079 100644 --- a/lib/skate_web/controllers/detours_controller.ex +++ b/lib/skate_web/controllers/detours_controller.ex @@ -32,7 +32,11 @@ defmodule SkateWeb.DetoursController do def detours(conn, _params) do %{id: user_id} = AuthManager.Plug.current_resource(conn) - detours = Detours.grouped_detours(user_id) + detours = %{ + active: Detours.detours_for_user(user_id, :active), + draft: Detours.detours_for_user(user_id, :draft), + past: Detours.detours_for_user(user_id, :past) + } json(conn, %{data: detours}) end From 37da28ce9e6aed17d70e69e7b2d9d55f42782c53 Mon Sep 17 00:00:00 2001 From: Brian Fauble Date: Tue, 18 Feb 2025 11:37:18 -0700 Subject: [PATCH 5/5] make grouped detours calls async --- lib/skate_web/controllers/detours_controller.ex | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/skate_web/controllers/detours_controller.ex b/lib/skate_web/controllers/detours_controller.ex index 329ee3079..5545a8fb1 100644 --- a/lib/skate_web/controllers/detours_controller.ex +++ b/lib/skate_web/controllers/detours_controller.ex @@ -32,11 +32,13 @@ defmodule SkateWeb.DetoursController do def detours(conn, _params) do %{id: user_id} = AuthManager.Plug.current_resource(conn) - detours = %{ - active: Detours.detours_for_user(user_id, :active), - draft: Detours.detours_for_user(user_id, :draft), - past: Detours.detours_for_user(user_id, :past) - } + detours = + [:active, :draft, :past] + |> Enum.map(fn status -> + Task.async(fn -> {status, Detours.detours_for_user(user_id, status)} end) + end) + |> Task.await_many() + |> Map.new() json(conn, %{data: detours}) end