Skip to content

Commit

Permalink
leverage ETS for site config instead of registry
Browse files Browse the repository at this point in the history
to increase throughput since that config is used everywhere
  • Loading branch information
leandrocp committed Aug 18, 2023
1 parent 57754f3 commit b1ccf7c
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 58 deletions.
2 changes: 1 addition & 1 deletion lib/beacon/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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__)
Expand Down
2 changes: 1 addition & 1 deletion lib/beacon/authorization.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
25 changes: 23 additions & 2 deletions lib/beacon/config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ defmodule Beacon.Config do
"""

alias Beacon.Content
alias Beacon.Registry

@ets_table :beacon_config

@typedoc """
Host application endpoint
Expand Down Expand Up @@ -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 """
Expand Down
31 changes: 1 addition & 30 deletions lib/beacon/registry.ex
Original file line number Diff line number Diff line change
@@ -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.
"""
Expand All @@ -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
8 changes: 6 additions & 2 deletions lib/beacon/site_supervisor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
27 changes: 27 additions & 0 deletions test/beacon/config_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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 %{
Expand Down
22 changes: 0 additions & 22 deletions test/beacon/registry_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit b1ccf7c

Please sign in to comment.