Live config supporting many different backends.
Kungfuig (pronounced: [ˌkʌŋˈfig]) provides an easy way to plug live configuration into everything.
It provides backends for env
and system
and supports custom backends.
def deps do
[
{:kungfuig, "~> 0.1"}
]
end
Kungfuig is the easy way to read the external configuration from sources that are not controlled by the application using it, such as Redis, or Database.
Here is the example of backend implementation for the config read from external MySQL.
defmodule MyApp.Kungfuig.MySQL do
@moduledoc false
use Kungfuig.Backend
@impl Kungfuig.Backend
def get(_meta) do
with {:ok, host} <- System.fetch_env("MYSQL_HOST"),
{:ok, db} <- System.fetch_env("MYSQL_DB"),
{:ok, user} <- System.fetch_env("MYSQL_USER"),
{:ok, pass} <- System.fetch_env("MYSQL_PASS"),
{:ok, pid} when is_pid(pid) <-
MyXQL.start_link(hostname: host, database: db, username: user, password: pass),
result <- MyXQL.query!(pid, "SELECT * FROM some_table") do
GenServer.stop(pid)
result =
result.rows
|> Flow.from_enumerable()
|> Flow.map(fn [_, field1, field2, _, _] -> {field1, field2} end)
|> Flow.partition(key: &elem(&1, 0))
|> Flow.reduce(fn -> %{} end, fn {field1, field2}, acc ->
Map.update(
acc,
String.to_existing_atom(field1),
[field2],
&[field2 | &1]
)
end)
Logger.info("Loaded #{Enum.count(result)} values from " <> host)
{:ok, result}
else
:error ->
Logger.warn("Skipped reconfig, one of MYSQL_{HOST,DB,USER,PASS} is missing")
:ok
error ->
Logger.error("Reconfiguring failed. Error: " <> inspect(error))
{:error, error}
end
end
end
Simply implement a stub returning an expected config and you are all set.
defmodule MyApp.Kungfuig.Stub do
@moduledoc false
use Kungfuig.Backend
@impl Kungfuig.Backend
def get(_meta), do: %{foo: :bar, baz: [42]}
end
1.0.0
— modern Elixir v1.160.4.4
— fix a bug with hardcoded names (Supervisor
andBlender
)0.4.2
— allowimminent: true
option toKungfuig.Backend
0.4.0
— allow namedKungfuig.Supervisor
(thanks @vbroskas)0.3.0
— allow validation throughNimbleOptions
(per backend and global)0.2.0
— scaffold for backends + several callbacks (and the automatic one forBlender
)