From b1ccf7c6d3f2637cb16760f9b675987e1f69f961 Mon Sep 17 00:00:00 2001 From: Leandro Pereira Date: Fri, 18 Aug 2023 10:26:11 -0400 Subject: [PATCH] leverage ETS for site config instead of registry to increase throughput since that config is used everywhere --- lib/beacon/application.ex | 2 +- lib/beacon/authorization.ex | 2 +- lib/beacon/config.ex | 25 +++++++++++++++++++++++-- lib/beacon/registry.ex | 31 +------------------------------ lib/beacon/site_supervisor.ex | 8 ++++++-- test/beacon/config_test.exs | 27 +++++++++++++++++++++++++++ test/beacon/registry_test.exs | 22 ---------------------- 7 files changed, 59 insertions(+), 58 deletions(-) diff --git a/lib/beacon/application.ex b/lib/beacon/application.ex index e49392835..71c2136e1 100644 --- a/lib/beacon/application.ex +++ b/lib/beacon/application.ex @@ -15,7 +15,7 @@ defmodule Beacon.Application do ] Beacon.Router.init() - + Beacon.Config.init() :ets.new(:beacon_assets, [:set, :named_table, :public, read_concurrency: true]) Supervisor.start_link(children, strategy: :one_for_one, name: __MODULE__) diff --git a/lib/beacon/authorization.ex b/lib/beacon/authorization.ex index c2e0b7fbc..3c5cfb313 100644 --- a/lib/beacon/authorization.ex +++ b/lib/beacon/authorization.ex @@ -52,6 +52,6 @@ defmodule Beacon.Authorization do end defp get_authorization_source(site) do - Beacon.Registry.config!(site).authorization_source + Beacon.Config.fetch!(site).authorization_source end end diff --git a/lib/beacon/config.ex b/lib/beacon/config.ex index 3642435d4..d67688885 100644 --- a/lib/beacon/config.ex +++ b/lib/beacon/config.ex @@ -7,7 +7,8 @@ defmodule Beacon.Config do """ alias Beacon.Content - alias Beacon.Registry + + @ets_table :beacon_config @typedoc """ Host application endpoint @@ -392,12 +393,32 @@ defmodule Beacon.Config do struct!(__MODULE__, opts) end + @doc false + def init do + :ets.new(@ets_table, [:set, :named_table, :public, read_concurrency: true]) + end + + @doc false + def insert!(site, config) do + true = :ets.insert_new(@ets_table, {site, config}) + :ok + end + @doc """ Returns the `Beacon.Config` for `site`. """ @spec fetch!(Beacon.Types.Site.t()) :: t() def fetch!(site) when is_atom(site) do - Registry.config!(site) + [{^site, config}] = :ets.lookup(@ets_table, site) + config + rescue + _ -> + reraise """ + could not find configuration for site #{site} + + Make sure it was started and configured correctly. See `Beacon.start_link/1` for more info. + """, + __STACKTRACE__ end @doc """ diff --git a/lib/beacon/registry.ex b/lib/beacon/registry.ex index 79e76aa4f..3c408bc7c 100644 --- a/lib/beacon/registry.ex +++ b/lib/beacon/registry.ex @@ -1,35 +1,12 @@ defmodule Beacon.Registry do - @moduledoc """ - Site process storage. + @moduledoc false - Each site `Beacon.Config` is stored in this registry. - """ - - @doc false def child_spec(_arg) do Registry.child_spec(keys: :unique, name: __MODULE__) end - @doc false def via(key), do: {:via, Registry, {__MODULE__, key}} - @doc false - def via(key, value), do: {:via, Registry, {__MODULE__, key, value}} - - @doc false - def config!(site) do - case lookup({:site, site}) do - {_pid, config} -> - config - - _ -> - raise RuntimeError, """ - Site #{inspect(site)} was not found. Make sure it's configured and started, - see `Beacon.start_link/1` for more info. - """ - end - end - @doc """ Return a list of all running sites in the current node. """ @@ -41,10 +18,4 @@ defmodule Beacon.Registry do Registry.select(__MODULE__, [{match, guards, body}]) end - - defp lookup(site) do - __MODULE__ - |> Registry.lookup(site) - |> List.first() - end end diff --git a/lib/beacon/site_supervisor.ex b/lib/beacon/site_supervisor.ex index e2f520978..d3ddde905 100644 --- a/lib/beacon/site_supervisor.ex +++ b/lib/beacon/site_supervisor.ex @@ -5,7 +5,7 @@ defmodule Beacon.SiteSupervisor do alias Beacon.Registry def start_link(config) do - Supervisor.start_link(__MODULE__, config, name: Registry.via({:site, config.site}, config)) + Supervisor.start_link(__MODULE__, config, name: Registry.via({:site, config.site})) end @impl true @@ -21,6 +21,10 @@ defmodule Beacon.SiteSupervisor do ] end - Supervisor.init(children, strategy: :one_for_one) + supervisor = Supervisor.init(children, strategy: :one_for_one) + + Beacon.Config.insert!(config.site, config) + + supervisor end end diff --git a/test/beacon/config_test.exs b/test/beacon/config_test.exs index 7d11c63c5..4053e96da 100644 --- a/test/beacon/config_test.exs +++ b/test/beacon/config_test.exs @@ -3,6 +3,33 @@ defmodule Beacon.ConfigTest do alias Beacon.Config + describe "storage" do + test "insert" do + assert Config.insert!(:config_test, %{foo: :bar}) == :ok + assert Config.fetch!(:config_test) == %{foo: :bar} + end + + test "return site config for existing sites" do + assert %Beacon.Config{ + css_compiler: Beacon.TailwindCompiler, + data_source: Beacon.BeaconTest.BeaconDataSource, + authorization_source: Beacon.BeaconTest.BeaconAuthorizationSource, + live_socket_path: "/custom_live", + safe_code_check: false, + site: :my_site, + tailwind_config: tailwind_config + } = Config.fetch!(:my_site) + + assert tailwind_config =~ "tailwind.config.js.eex" + end + + test "raise when not found" do + assert_raise RuntimeError, ~r/could not find configuration for site invalid/, fn -> + Config.fetch!(:invalid) + end + end + end + describe "template_formats" do test "preserve default config" do assert %{ diff --git a/test/beacon/registry_test.exs b/test/beacon/registry_test.exs index 3729fbb2f..b039d14f0 100644 --- a/test/beacon/registry_test.exs +++ b/test/beacon/registry_test.exs @@ -7,26 +7,4 @@ defmodule Beacon.RegistryTest do running_sites = Registry.running_sites() assert Enum.sort(running_sites) == [:data_source_test, :default_meta_tags_test, :lifecycle_test, :lifecycle_test_fail, :my_site, :s3_site] end - - describe "config!" do - test "return site config for existing sites" do - assert %Beacon.Config{ - css_compiler: Beacon.TailwindCompiler, - data_source: Beacon.BeaconTest.BeaconDataSource, - authorization_source: Beacon.BeaconTest.BeaconAuthorizationSource, - live_socket_path: "/custom_live", - safe_code_check: false, - site: :my_site, - tailwind_config: tailwind_config - } = Registry.config!(:my_site) - - assert tailwind_config =~ "tailwind.config.js.eex" - end - - test "raise when not found" do - assert_raise RuntimeError, ~r/Site :invalid was not found/, fn -> - Registry.config!(:invalid) - end - end - end end