[erlang-questions] Use of application environment
Serge Aleynikov
saleyn@REDACTED
Wed Dec 3 14:01:17 CET 2008
Edwin Fine wrote:
> I assume, reading the code you linked to, that one still needs to include in
> the config_change callback something to propagate the changes to the various
> workers and supervisors. Do you think that the subscribe/notify mechanism I
> described is workable?
Frankly, I think this is a bit over-engineered, as you'd need to deal
with re-subscription in every worker. Since the config_change event
gives you a reactivity callback to configuration changes, the rest that
you need is a "standard" way to expose configuration change requests in
every worker. One other approach would be to implement the following
two functions in each worker process:
options() -> [Param::atom()].
reconfig(AddedOptions, ChangedOptions, DeletedOptions) -> Result
Result = ok | {error, Reason}
AddedOptions = ChangedOptions = DeletedOptions =
[{Param::atom(), Value}]
or perhaps, just:
options() -> [Param::atom()].
reconfig(Options) -> ok | {error, Reason}
Options = [{Param::atom(), Value}]
Then the application's config_change/3 callback would just go through
the list of modules in the app and do:
Options = ...,
Modules = ...,
lists:foreach(fun(M) ->
Opts = [O || O <- Options, lists:member(O, M:options())],
M:reconfig(Opts)
end, Modules).
>
>> This is a simplistic approach that doesn't involve configuration
>> validation. Actually this was a part of a configuration management
>> framework that we developed at my former employer that included a
>> configuration server that maintained the versioned configuration repository
>> that also performed syntax verification based on the application's metadata
>> deployed with each app that included all needed parameters for each
>> environment type (e.g. prod/dev/qa/etc), parameter types, defaults, update
>> actions (such as reload environment, restart application, restart node,
>> etc.), parameter documentation. The server would perform configuration
>> validation based on this metadata and reject unconformable input. Each node
>> would run a configuration client that upon startup would query the
>> configuration server and rebuild the local configuration file if there were
>> any parameter changes. It would then use that configuration file in
>> starting a release.
>
> That's pretty sophisticated and along the lines of what I had envisioned.
> It's a pity I don't have the time to write something like that. Your former
> employer was evidently unlucky to lose you :)
Given the need to support a family of three kids and the state of
telecom at a time the switch to financial industry was quite
indispensable... ;-)
> Do you by any chance remember if the metadata was able to describe complex
> terms involving nested lists and tuples? Also, do you know of something like
> type_of(Term) (besides is_integer/1 and the others) available somewhere in
> Erlang?
Yes, the meta parameter info was in the form:
%%% @type param_spec() = ParamSpec
%%% ParamSpec = {Param,Desc,TypeSpec,Default,Required,Restart}
%%% Param = atom()
%%% Desc = string()
%%% TypeSpec = expected_type()
%%% Default = term()
%%% Required = true | false
%%% Restart = reload | application | restart | reboot
And specification language for expected_type() was something like
(incomplete):
%%% @type expected_type() = ExpectedType
%%% ExpectedType = atom | {value, ValidItems::list()} |
%%% tuple | boolean |string |ip_address |ip_port |ip_tuple |
%%% integer | {integer, Min::integer(), Max::integer()} |
%%% float | {float, Min::float(), Max::float()} |
%%% list | {list, ValidItems::list()} | {list_of, Type} |
%%% {func, FunStr::string()} |
%%% {func, TypeDescBin::binary(), FunStr::string()}
%%% Type = integer | float | atom | list | tuple | ip_address |
%%% ip_port | number | string | ValidItems | node |
%%% TupleType
%%% TupleType = { ExpectedType }
%%% Fun = (Opt, Value) -> ok |
%%% throw({error, {bad_config, {Key, Val}, Reason}})
%%% ValidItems = list()
So an example of meta parameter definition would be:
[{param1, <<"Docs for param1">>, {integer, 0, 100}, 0, true, reload},
{param2, <<"Docs for param2">> , string, "", true, reload},
{param3, <<"Docs for param3">> , {list, [one,two,three]}, [one], true,
reload},
{param4, <<"Name/Val List">>, {list_of, [{{value, [one]}, string},
{{value, [two]}, integer}]}, [], true, reload}],
Note that the param3 can take a value of 'one', 'two' or 'three'. And
the param4 can take a list of name/value pairs, such as:
[{one, "example"}, {two, 2}]
Regards,
Serge
More information about the erlang-questions
mailing list