defmodule DaProductApp.GlobalSettings do @moduledoc """ GenServer that caches global settings from `global_table` in ShukriaMms database. - Loads settings at startup - Periodically refreshes (default 10 minutes) - Exposes `get_all/0`, `get/1` and `refresh/0` API """ use GenServer require Logger alias DaProductApp.Repos.ShukriaMmsRepo import Ecto.Query @name __MODULE__ @refresh_ms Application.get_env(:da_product_app, :global_settings_refresh_ms, :timer.minutes(10)) # Public API def start_link(_opts) do GenServer.start_link(__MODULE__, %{}, name: @name) end def get_all do GenServer.call(@name, :get_all) end def get(key) do Map.get(get_all(), to_string(key)) end def refresh do GenServer.cast(@name, :refresh) end # Callbacks @impl true def init(_args) do state = load_once(%{}) if is_integer(@refresh_ms) and @refresh_ms > 0 do :timer.send_interval(@refresh_ms, :refresh) end {:ok, state} end @impl true def handle_call(:get_all, _from, state) do {:reply, state, state} end @impl true def handle_cast(:refresh, state) do {:noreply, load_once(state)} end @impl true def handle_info(:refresh, state) do {:noreply, load_once(state)} end defp load_once(current_state) do query = from(g in "global_table", select: {g.config_key, g.config_value}) case ShukriaMmsRepo.all(query) do rows when is_list(rows) -> rows |> Enum.into(%{}, fn {k, v} -> {to_string(k), v} end) _ -> Logger.error("GlobalSettings: unexpected response loading settings, keeping last-known state") current_state end rescue e -> Logger.error("GlobalSettings load error: #{inspect(e)} - keeping last-known state") current_state end end