defmodule Vela.Cache.Config do @moduledoc """ Configuration struct for a Vela cache instance. """ @type eviction_policy :: :lru | :lfu | :fifo | :ttl_only @type topology :: module() @type backend :: module() @type t :: %__MODULE__{ name: atom(), backend: backend(), backend_opts: keyword(), topology: topology(), topology_opts: keyword(), near_cache: boolean(), near_cache_l1_ttl: non_neg_integer(), default_ttl: non_neg_integer() | :infinity, max_size: non_neg_integer() | :infinity, eviction_policy: eviction_policy(), stampede_protection: boolean(), stampede_timeout: non_neg_integer(), stats_enabled: boolean(), telemetry_prefix: [atom()], sweep_interval: non_neg_integer() } defstruct [ :name, backend: Vela.Backend.ETS, backend_opts: [], topology: Vela.Topology.Local, topology_opts: [], near_cache: false, near_cache_l1_ttl: 60_000, default_ttl: :infinity, max_size: :infinity, eviction_policy: :ttl_only, stampede_protection: true, stampede_timeout: 5_000, stats_enabled: true, telemetry_prefix: [:vela, :cache], sweep_interval: 30_000 ] @doc """ Builds a Config from a keyword list, applying library defaults. """ @spec new(atom(), keyword()) :: t() def new(name, opts) do # Read library-wide defaults from application config # e.g. config :vela, default_sweep_interval: 60_000 app_defaults = Application.get_all_env(:vela) fields = struct_fields() |> Enum.map(fn {key, _default} -> value = Keyword.get(opts, key) || Keyword.get(app_defaults, key) || Map.get(%__MODULE__{}, key) {key, value} end) |> Keyword.put(:name, name) struct(__MODULE__, fields) end # Returns all struct field names with their defaults defp struct_fields do %__MODULE__{} |> Map.from_struct() |> Map.to_list() end end