Current section
Files
Jump to
Current section
Files
lib/cache_manager.ex
defmodule ISRPlug.CacheManager do
@moduledoc """
Manages ETS tables for ISRPlug. Add to your Application supervisor.
"""
use GenServer
require Logger
alias ISRPlug
# --- Public API ---
@doc """
Starts the cache manager. Called by the application supervisor.
Opts:
- table_names: list of atoms, ETS tables to create. Defaults to [:isr_plug_cache]
"""
def start_link(opts) do
# Use the module name as the GenServer registered name
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end
# --- GenServer Callbacks ---
@impl true
def init(opts) do
# Default to the table name expected by ISRPlug if none are passed
default_table = ISRPlug.default_ets_table()
table_names = Keyword.get(opts, :table_names, [default_table]) |> List.wrap() |> Enum.uniq()
ets_options = [
:set,
:public,
:named_table,
read_concurrency: true,
write_concurrency: true
]
Logger.info("[#{__MODULE__}] Initializing ETS tables: #{inspect(table_names)}")
# Create each requested table
Enum.each(table_names, fn table_name ->
create_table_if_needed(table_name, ets_options)
end)
# No real state needed after init
{:ok, %{managed_tables: table_names}}
end
# --- Private Helpers ---
defp create_table_if_needed(table_name, ets_options) when is_atom(table_name) do
# Check if table already exists (important for restarts/idempotency)
unless :ets.info(table_name, :name) == table_name do
Logger.info("[#{inspect(__MODULE__)}] Creating ETS table: #{inspect(table_name)}")
:ets.new(table_name, ets_options)
else
Logger.info("[#{inspect(__MODULE__)}] ETS table already exists: #{inspect(table_name)}")
end
rescue
# If creation fails, log and crash supervisor init (prevents broken app state)
error ->
Logger.error(
"[#{inspect(__MODULE__)}] Failed to create ETS table #{inspect(table_name)}: #{inspect(error)}"
)
reraise error, __STACKTRACE__
end
defp create_table_if_needed(invalid_name, _ets_options) do
msg =
"Invalid ETS table name provided to #{__MODULE__}: #{inspect(invalid_name)}. Must be an atom."
Logger.error(msg)
raise ArgumentError, msg
end
end