Current section
Files
Jump to
Current section
Files
lib/spring_config.ex
defmodule SpringConfig do
@moduledoc """
Consume configuration from a Spring Cloud Config Server in Elixir.
"""
use PatternTap
@default_opts []
@spec get(atom(), any(), keyword()) :: any()
@doc """
Finds and returns `key` in the configuration registry. If `key` is not found, `default` is returned.
Available options are:
- `ensure_started`: Uses `Application.ensure_all_started/2` to start the SpringConfig application
temporarily in case the process is not part of the supervision tree. Default `false`.
"""
def get(key, default \\ nil, opts \\ []) when is_atom(key) do
opts = Keyword.merge(@default_opts, opts)
if opts[:ensure_started] do
{:ok, _} = Application.ensure_all_started(:spring_config)
end
key |> to_string() |> String.split(".") |> Enum.map(&String.to_atom/1) |> do_get(default)
end
@spec get!(atom(), keyword()) :: any()
@doc """
Similar to `get/3` but raises if `key` is not found.
"""
def get!(key, opts \\ []) when is_atom(key) do
case get(key, :default_value, opts) do
:default_value ->
raise "Key #{key} not found in configuration entries"
value ->
value
end
end
defp do_get(keys, default) do
case :ets.select(:spring_config, [{{keys ++ :"$1", :"$2"}, [], [{{:"$1", :"$2"}}]}]) do
[] ->
default
result ->
transform(result)
end
end
defp transform(entries) do
Enum.reduce(entries, %{}, fn
{[], value}, _out ->
value
{keys, value}, map ->
map
|> create_path(keys)
|> put_in(keys, value)
end)
end
defp create_path(map, keys) do
keys
|> Enum.reduce({map, []}, fn
key, {map, []} ->
{Map.put_new(map, key, nil), [key]}
key, {map, prev_keys} ->
new_map =
update_in(map, prev_keys, fn
nil -> %{key => nil}
val -> val
end)
{new_map, prev_keys ++ [key]}
end)
|> tap({map, _} ~> map)
end
end