Dynamic Configuration Database in Erlang

zxq9 zxq9@REDACTED
Wed Dec 4 16:08:52 CET 2019


On 2019/12/04 22:03, Stefano Bertuola wrote:
> I am looking for understanding how to implement a configuration database 
> in Erlang (which allows dynamic configuration).
> 
> Does anyone have more details about this or any other implementation?

Hi, Stefano.

I make a configuration manager/DB in just about any program I write that 
needs configuration. Usually this takes the form of a single gen_server 
that is started first at the beginning of execution (you can have it 
start later, but usually your system configuration is pretty close to 
the very top of your supervision tree).

You can implement a relatively naked "global dictionary" if you haven't 
figured out what sort of configuration data your program needs. This 
would be a simple process that exposes two functions:

-spec config(Key :: atom()) -> Value :: term().
-spec config(Key :: atom(), Value :: term()) -> ok.

This is as naive as things can possibly get and is really just a wrapper 
over either a front-end for an ETS table or a gen_server that simply 
keeps a config map of #{Key => Value} in its state.

(I often avoid ETS unless it becomes an actual *need* in a program, 
which is somewhat rare. As long as you hide the act of accessing the 
config data behind functions it doesn't matter which approach you take 
to start out with because you can change things later -- just don't get 
into the habit of scattering naked reads from ETS tables throughout your 
code!)

While this is naive it is not a *bad* way to start playing with the idea 
of a config manager within your programs (and even this naive approach 
already gives you the magic ability to alter global settings on the 
fly), but a config manager can be much more useful.

In client-side programs you often have a large amount of evolving state 
that the user expects to persist between executions, or settings they 
can change globally across the program (for example, changing a l10n 
option or adding/removing a plugin in naive programs very often requires 
restarting the program -- that's unsatisfactory in many cases). In 
complex server-side programs there may be a huge amount of configuration 
data about who to contact, what connections must be established and so on.

In those cases "config" doesn't just mean "read the config file" (though 
it usually involves that), but also often means "try to acquire external 
resources that may require discovery first". In this case the 
configuration manager process is where you can codify the discovery 
logic, default settings, config failure criteria (to cause a clean exit 
with appropriate logs/warnings/alerts sent), and other config 
initialization or safe/unsafe update checks. It can also be used as a 
place to register processes that need to be notified when config update 
events occur (imagine having a function where a process can register for 
config updates "send me a notification if Key/Value is changed", for 
example).

The more complex a program's configuration state becomes the more often 
you'll find yourself writing specific functions to handle specific 
config keys and states (or specific clauses of an exposed config/2 
function that match on specific keys) because config changes have a way 
over time of interacting with one another and requiring sanity checks 
that are better to formalize within a config manager module than scatter 
around in ad-hoc code.

I'm explaining this in prose instead of providing an example, but 
hopefully this gives you some ideas. Write a config manager and play 
around with the idea. Having a config manager process at the top of your 
supervision tree (and offloading it from ad-hoc config management 
throughout the rest of the code) can sometimes make a lot of other code 
simpler to test, debug and comprehend.

-Craig



More information about the erlang-questions mailing list