Skip to content

Commit

Permalink
feat: cache routes by id to speed up alerts filtering (#2142)
Browse files Browse the repository at this point in the history
* feat: cache routes

* feat: use route cache in alerts filter expansion
  • Loading branch information
sloanelybutsurely authored Aug 19, 2024
1 parent f07d595 commit 6f88363
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 6 deletions.
1 change: 1 addition & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ config :screens, Screens.ScreenApiResponseCache,
allocated_memory: 250_000_000

config :screens, Screens.Stops.StopsToRoutes, adapter: Nebulex.Adapters.Local
config :screens, Screens.Routes.RoutesCache, adapter: Nebulex.Adapters.Local

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
Expand Down
3 changes: 2 additions & 1 deletion config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ config :screens,
blue_bikes_station_status_url: [:no_api_requests_allowed_during_testing],
blue_bikes_api_client: Screens.BlueBikes.FakeClient,
stops_to_routes_route_mod: Screens.Routes.Route.Mock,
alerts_cache_filter_route_mod: Screens.Routes.Route.Mock,
routes_cache_route_mod: Screens.Routes.Route.Mock,
dup_headsign_replacements: %{
"Test 1" => "T1"
},
Expand Down Expand Up @@ -164,3 +164,4 @@ config :screens, :screens_by_alert,
screens_ttl_seconds: 1

config :screens, Screens.Stops.StopsToRoutes, adapter: Nebulex.Adapters.Nil
config :screens, Screens.Routes.RoutesCache, adapter: Nebulex.Adapters.Nil
7 changes: 3 additions & 4 deletions lib/screens/alerts/cache/filter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ defmodule Screens.Alerts.Cache.Filter do
Logic to apply filters to a list of `Screens.Alerts.Alert` structs.
"""
alias Screens.Routes.Route
alias Screens.Routes.RoutesCache
alias Screens.RouteType
alias Screens.Stops.StopsToRoutes

@route_mod Application.compile_env(:screens, :alerts_cache_filter_route_mod, Route)

@default_activities ~w[BOARD EXIT RIDE]

@type filter_opts() :: %{
Expand Down Expand Up @@ -127,8 +126,8 @@ defmodule Screens.Alerts.Cache.Filter do
end

defp matchers_for_route_id(route_id) do
case @route_mod.by_id(route_id) do
{:ok, %Route{type: type}} ->
case RoutesCache.by_id(route_id) do
%Route{type: type} ->
[
%{
route_type: RouteType.to_id(type),
Expand Down
3 changes: 2 additions & 1 deletion lib/screens/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ defmodule Screens.Application do
{Screens.OlCrowding.Agent, %{}},
{Screens.ScreenApiResponseCache, []},
Screens.Streams.Alerts,
Screens.Stops.StopsToRoutes
Screens.Stops.StopsToRoutes,
Screens.Routes.RoutesCache
]

# See https://hexdocs.pm/elixir/Supervisor.html
Expand Down
39 changes: 39 additions & 0 deletions lib/screens/routes/routes_cache.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
defmodule Screens.Routes.RoutesCache do
@moduledoc """
A read-through cache of routes by ID.
"""
use Nebulex.Cache,
otp_app: :screens,
adapter: Application.compile_env(:screens, [__MODULE__, :adapter])

alias Screens.Routes.Route

@route_mod Application.compile_env(:screens, :routes_cache_route_mod, Screens.Routes.Route)

@base_ttl :timer.hours(1)

@spec by_id(id :: String.t()) :: Route.t() | nil
def by_id(id) do
if route = get(id) do
route
else
route = fetch_by_id(id)

unless is_nil(route), do: put(id, route, ttl: ttl())

route
end
end

defp fetch_by_id(id) do
case @route_mod.by_id(id) do
{:ok, %Route{} = route} -> route
_ -> nil
end
end

def ttl do
additional_minutes = :rand.uniform(30)
@base_ttl + :timer.minutes(additional_minutes)
end
end

0 comments on commit 6f88363

Please sign in to comment.