feat(config): support wildcard paths for config handlers
This commit is contained in:
parent
be0fd6fddd
commit
60b8215360
|
@ -39,6 +39,7 @@
|
||||||
code_change/3]).
|
code_change/3]).
|
||||||
|
|
||||||
-define(MOD, {mod}).
|
-define(MOD, {mod}).
|
||||||
|
-define(WKEY, '?').
|
||||||
|
|
||||||
-define(ATOM_CONF_PATH(PATH, EXP, EXP_ON_FAIL),
|
-define(ATOM_CONF_PATH(PATH, EXP, EXP_ON_FAIL),
|
||||||
try [safe_atom(Key) || Key <- PATH] of
|
try [safe_atom(Key) || Key <- PATH] of
|
||||||
|
@ -80,11 +81,11 @@ update_config(SchemaModule, ConfKeyPath, UpdateArgs) ->
|
||||||
|
|
||||||
-spec add_handler(emqx_config:config_key_path(), handler_name()) -> ok.
|
-spec add_handler(emqx_config:config_key_path(), handler_name()) -> ok.
|
||||||
add_handler(ConfKeyPath, HandlerName) ->
|
add_handler(ConfKeyPath, HandlerName) ->
|
||||||
gen_server:call(?MODULE, {add_child, ConfKeyPath, HandlerName}).
|
gen_server:call(?MODULE, {add_handler, ConfKeyPath, HandlerName}).
|
||||||
|
|
||||||
-spec remove_handler(emqx_config:config_key_path()) -> ok.
|
-spec remove_handler(emqx_config:config_key_path()) -> ok.
|
||||||
remove_handler(ConfKeyPath) ->
|
remove_handler(ConfKeyPath) ->
|
||||||
gen_server:call(?MODULE, {remove_child, ConfKeyPath}).
|
gen_server:call(?MODULE, {remove_handler, ConfKeyPath}).
|
||||||
|
|
||||||
%%============================================================================
|
%%============================================================================
|
||||||
|
|
||||||
|
@ -92,15 +93,18 @@ remove_handler(ConfKeyPath) ->
|
||||||
init(_) ->
|
init(_) ->
|
||||||
{ok, #{handlers => #{?MOD => ?MODULE}}}.
|
{ok, #{handlers => #{?MOD => ?MODULE}}}.
|
||||||
|
|
||||||
handle_call({add_child, ConfKeyPath, HandlerName}, _From,
|
handle_call({add_handler, ConfKeyPath, HandlerName}, _From, State = #{handlers := Handlers}) ->
|
||||||
State = #{handlers := Handlers}) ->
|
case deep_put_handler(ConfKeyPath, Handlers, HandlerName) of
|
||||||
{reply, ok, State#{handlers =>
|
{ok, NewHandlers} ->
|
||||||
emqx_map_lib:deep_put(ConfKeyPath, Handlers, #{?MOD => HandlerName})}};
|
{reply, ok, State#{handlers => NewHandlers}};
|
||||||
|
Error ->
|
||||||
|
{reply, Error, State}
|
||||||
|
end;
|
||||||
|
|
||||||
handle_call({remove_child, ConfKeyPath}, _From,
|
handle_call({remove_handler, ConfKeyPath}, _From,
|
||||||
State = #{handlers := Handlers}) ->
|
State = #{handlers := Handlers}) ->
|
||||||
{reply, ok, State#{handlers =>
|
{reply, ok, State#{handlers =>
|
||||||
emqx_map_lib:deep_remove(ConfKeyPath, Handlers)}};
|
emqx_map_lib:deep_remove(ConfKeyPath ++ [?MOD], Handlers)}};
|
||||||
|
|
||||||
handle_call({change_config, SchemaModule, ConfKeyPath, UpdateArgs}, _From,
|
handle_call({change_config, SchemaModule, ConfKeyPath, UpdateArgs}, _From,
|
||||||
#{handlers := Handlers} = State) ->
|
#{handlers := Handlers} = State) ->
|
||||||
|
@ -134,6 +138,27 @@ terminate(_Reason, _State) ->
|
||||||
code_change(_OldVsn, State, _Extra) ->
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
{ok, State}.
|
{ok, State}.
|
||||||
|
|
||||||
|
deep_put_handler([], _Handlers, Mod) ->
|
||||||
|
{ok, #{?MOD => Mod}};
|
||||||
|
deep_put_handler([?WKEY | KeyPath], Handlers, Mod) ->
|
||||||
|
deep_put_handler2(?WKEY, KeyPath, Handlers, Mod);
|
||||||
|
deep_put_handler([Key | KeyPath], Handlers, Mod) ->
|
||||||
|
case maps:find(?WKEY, Handlers) of
|
||||||
|
error ->
|
||||||
|
deep_put_handler2(Key, KeyPath, Handlers, Mod);
|
||||||
|
{ok, _SubHandlers} ->
|
||||||
|
{error, {cannot_override_a_wildcard_path, [?WKEY | KeyPath]}}
|
||||||
|
end.
|
||||||
|
|
||||||
|
deep_put_handler2(Key, KeyPath, Handlers, Mod) ->
|
||||||
|
SubHandlers = maps:get(Key, Handlers, #{}),
|
||||||
|
case deep_put_handler(KeyPath, SubHandlers, Mod) of
|
||||||
|
{ok, SubHandlers1} ->
|
||||||
|
{ok, Handlers#{Key => SubHandlers1}};
|
||||||
|
Error ->
|
||||||
|
Error
|
||||||
|
end.
|
||||||
|
|
||||||
process_update_request(ConfKeyPath, _Handlers, {remove, Opts}) ->
|
process_update_request(ConfKeyPath, _Handlers, {remove, Opts}) ->
|
||||||
OldRawConf = emqx_config:get_root_raw(ConfKeyPath),
|
OldRawConf = emqx_config:get_root_raw(ConfKeyPath),
|
||||||
BinKeyPath = bin_path(ConfKeyPath),
|
BinKeyPath = bin_path(ConfKeyPath),
|
||||||
|
@ -153,7 +178,7 @@ do_update_config([], Handlers, OldRawConf, UpdateReq) ->
|
||||||
call_pre_config_update(Handlers, OldRawConf, UpdateReq);
|
call_pre_config_update(Handlers, OldRawConf, UpdateReq);
|
||||||
do_update_config([ConfKey | ConfKeyPath], Handlers, OldRawConf, UpdateReq) ->
|
do_update_config([ConfKey | ConfKeyPath], Handlers, OldRawConf, UpdateReq) ->
|
||||||
SubOldRawConf = get_sub_config(bin(ConfKey), OldRawConf),
|
SubOldRawConf = get_sub_config(bin(ConfKey), OldRawConf),
|
||||||
SubHandlers = maps:get(ConfKey, Handlers, #{}),
|
SubHandlers = get_sub_handlers(ConfKey, Handlers),
|
||||||
case do_update_config(ConfKeyPath, SubHandlers, SubOldRawConf, UpdateReq) of
|
case do_update_config(ConfKeyPath, SubHandlers, SubOldRawConf, UpdateReq) of
|
||||||
{ok, NewUpdateReq} ->
|
{ok, NewUpdateReq} ->
|
||||||
call_pre_config_update(Handlers, OldRawConf, #{bin(ConfKey) => NewUpdateReq});
|
call_pre_config_update(Handlers, OldRawConf, #{bin(ConfKey) => NewUpdateReq});
|
||||||
|
@ -184,7 +209,7 @@ do_post_config_update([ConfKey | ConfKeyPath], Handlers, OldConf, NewConf, AppEn
|
||||||
Result) ->
|
Result) ->
|
||||||
SubOldConf = get_sub_config(ConfKey, OldConf),
|
SubOldConf = get_sub_config(ConfKey, OldConf),
|
||||||
SubNewConf = get_sub_config(ConfKey, NewConf),
|
SubNewConf = get_sub_config(ConfKey, NewConf),
|
||||||
SubHandlers = maps:get(ConfKey, Handlers, #{}),
|
SubHandlers = get_sub_handlers(ConfKey, Handlers),
|
||||||
case do_post_config_update(ConfKeyPath, SubHandlers, SubOldConf, SubNewConf, AppEnvs,
|
case do_post_config_update(ConfKeyPath, SubHandlers, SubOldConf, SubNewConf, AppEnvs,
|
||||||
UpdateArgs, Result) of
|
UpdateArgs, Result) of
|
||||||
{ok, Result1} ->
|
{ok, Result1} ->
|
||||||
|
@ -193,6 +218,12 @@ do_post_config_update([ConfKey | ConfKeyPath], Handlers, OldConf, NewConf, AppEn
|
||||||
Error -> Error
|
Error -> Error
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
get_sub_handlers(ConfKey, Handlers) ->
|
||||||
|
case maps:find(ConfKey, Handlers) of
|
||||||
|
error -> maps:get(?WKEY, Handlers, #{});
|
||||||
|
{ok, SubHandlers} -> SubHandlers
|
||||||
|
end.
|
||||||
|
|
||||||
get_sub_config(ConfKey, Conf) when is_map(Conf) ->
|
get_sub_config(ConfKey, Conf) when is_map(Conf) ->
|
||||||
maps:get(ConfKey, Conf, undefined);
|
maps:get(ConfKey, Conf, undefined);
|
||||||
get_sub_config(_, _Conf) -> %% the Conf is a primitive
|
get_sub_config(_, _Conf) -> %% the Conf is a primitive
|
||||||
|
|
|
@ -65,13 +65,11 @@ deep_find(_KeyPath, Data) ->
|
||||||
{not_found, _KeyPath, Data}.
|
{not_found, _KeyPath, Data}.
|
||||||
|
|
||||||
-spec deep_put(config_key_path(), map(), term()) -> map().
|
-spec deep_put(config_key_path(), map(), term()) -> map().
|
||||||
deep_put([], Map, Data) when is_map(Map) ->
|
deep_put([], _Map, Data) ->
|
||||||
Data;
|
|
||||||
deep_put([], _Map, Data) -> %% not map, replace it
|
|
||||||
Data;
|
Data;
|
||||||
deep_put([Key | KeyPath], Map, Data) ->
|
deep_put([Key | KeyPath], Map, Data) ->
|
||||||
SubMap = deep_put(KeyPath, maps:get(Key, Map, #{}), Data),
|
SubMap = maps:get(Key, Map, #{}),
|
||||||
Map#{Key => SubMap}.
|
Map#{Key => deep_put(KeyPath, SubMap, Data)}.
|
||||||
|
|
||||||
-spec deep_remove(config_key_path(), map()) -> map().
|
-spec deep_remove(config_key_path(), map()) -> map().
|
||||||
deep_remove([], Map) ->
|
deep_remove([], Map) ->
|
||||||
|
|
Loading…
Reference in New Issue