refactor(emqx_config): move helper funcs to emqx_map_lib

This commit is contained in:
Shawn 2021-07-05 15:06:56 +08:00
parent a884d215e1
commit 30c2a76dae
4 changed files with 93 additions and 74 deletions

View File

@ -35,43 +35,34 @@
, put_raw/2 , put_raw/2
]). ]).
-export([ deep_get/2
, deep_get/3
, deep_put/3
, safe_atom_key_map/1
, unsafe_atom_key_map/1
]).
-define(CONF, ?MODULE). -define(CONF, ?MODULE).
-define(RAW_CONF, {?MODULE, raw}). -define(RAW_CONF, {?MODULE, raw}).
-export_type([update_request/0, raw_config/0, config_key/0, config_key_path/0]). -export_type([update_request/0, raw_config/0]).
-type update_request() :: term(). -type update_request() :: term().
-type raw_config() :: hocon:config() | undefined. -type raw_config() :: hocon:config() | undefined.
-type config_key() :: atom() | binary().
-type config_key_path() :: [config_key()].
-spec get() -> map(). -spec get() -> map().
get() -> get() ->
persistent_term:get(?CONF, #{}). persistent_term:get(?CONF, #{}).
-spec get(config_key_path()) -> term(). -spec get(emqx_map_lib:config_key_path()) -> term().
get(KeyPath) -> get(KeyPath) ->
deep_get(KeyPath, get()). emqx_map_lib:deep_get(KeyPath, get()).
-spec get(config_key_path(), term()) -> term(). -spec get(emqx_map_lib:config_key_path(), term()) -> term().
get(KeyPath, Default) -> get(KeyPath, Default) ->
deep_get(KeyPath, get(), Default). emqx_map_lib:deep_get(KeyPath, get(), Default).
-spec put(map()) -> ok. -spec put(map()) -> ok.
put(Config) -> put(Config) ->
persistent_term:put(?CONF, Config). persistent_term:put(?CONF, Config).
-spec put(config_key_path(), term()) -> ok. -spec put(emqx_map_lib:config_key_path(), term()) -> ok.
put(KeyPath, Config) -> put(KeyPath, Config) ->
put(deep_put(KeyPath, get(), Config)). put(emqx_map_lib:deep_put(KeyPath, get(), Config)).
-spec update_config(config_key_path(), update_request()) -> -spec update_config(emqx_map_lib:config_key_path(), update_request()) ->
ok | {error, term()}. ok | {error, term()}.
update_config(ConfKeyPath, UpdateReq) -> update_config(ConfKeyPath, UpdateReq) ->
emqx_config_handler:update_config(ConfKeyPath, UpdateReq, get_raw()). emqx_config_handler:update_config(ConfKeyPath, UpdateReq, get_raw()).
@ -80,66 +71,19 @@ update_config(ConfKeyPath, UpdateReq) ->
get_raw() -> get_raw() ->
persistent_term:get(?RAW_CONF, #{}). persistent_term:get(?RAW_CONF, #{}).
-spec get_raw(config_key_path()) -> term(). -spec get_raw(emqx_map_lib:config_key_path()) -> term().
get_raw(KeyPath) -> get_raw(KeyPath) ->
deep_get(KeyPath, get_raw()). emqx_map_lib:deep_get(KeyPath, get_raw()).
-spec get_raw(config_key_path(), term()) -> term(). -spec get_raw(emqx_map_lib:config_key_path(), term()) -> term().
get_raw(KeyPath, Default) -> get_raw(KeyPath, Default) ->
deep_get(KeyPath, get_raw(), Default). emqx_map_lib:deep_get(KeyPath, get_raw(), Default).
-spec put_raw(map()) -> ok. -spec put_raw(map()) -> ok.
put_raw(Config) -> put_raw(Config) ->
persistent_term:put(?RAW_CONF, Config). persistent_term:put(?RAW_CONF, Config).
-spec put_raw(config_key_path(), term()) -> ok. -spec put_raw(emqx_map_lib:config_key_path(), term()) -> ok.
put_raw(KeyPath, Config) -> put_raw(KeyPath, Config) ->
put_raw(deep_put(KeyPath, get_raw(), Config)). put_raw(emqx_map_lib:deep_put(KeyPath, get_raw(), Config)).
%%-----------------------------------------------------------------
-spec deep_get(config_key_path(), map()) -> term().
deep_get(ConfKeyPath, Map) ->
do_deep_get(ConfKeyPath, Map, fun(KeyPath, Data) ->
error({not_found, KeyPath, Data}) end).
-spec deep_get(config_key_path(), map(), term()) -> term().
deep_get(ConfKeyPath, Map, Default) ->
do_deep_get(ConfKeyPath, Map, fun(_, _) -> Default end).
-spec deep_put(config_key_path(), map(), term()) -> map().
deep_put([], Map, Config) when is_map(Map) ->
Config;
deep_put([Key | KeyPath], Map, Config) ->
SubMap = deep_put(KeyPath, maps:get(Key, Map, #{}), Config),
Map#{Key => SubMap}.
unsafe_atom_key_map(Map) ->
covert_keys_to_atom(Map, fun(K) -> binary_to_atom(K, utf8) end).
safe_atom_key_map(Map) ->
covert_keys_to_atom(Map, fun(K) -> binary_to_existing_atom(K, utf8) end).
%%---------------------------------------------------------------------------
-spec do_deep_get(config_key_path(), map(), fun((config_key(), term()) -> any())) -> term().
do_deep_get([], Map, _) ->
Map;
do_deep_get([Key | KeyPath], Map, OnNotFound) when is_map(Map) ->
case maps:find(Key, Map) of
{ok, SubMap} -> do_deep_get(KeyPath, SubMap, OnNotFound);
error -> OnNotFound(Key, Map)
end;
do_deep_get([Key | _KeyPath], Data, OnNotFound) ->
OnNotFound(Key, Data).
covert_keys_to_atom(BinKeyMap, Conv) when is_map(BinKeyMap) ->
maps:fold(
fun(K, V, Acc) when is_binary(K) ->
Acc#{Conv(K) => covert_keys_to_atom(V, Conv)};
(K, V, Acc) when is_atom(K) ->
%% richmap keys
Acc#{K => covert_keys_to_atom(V, Conv)}
end, #{}, BinKeyMap);
covert_keys_to_atom(ListV, Conv) when is_list(ListV) ->
[covert_keys_to_atom(V, Conv) || V <- ListV];
covert_keys_to_atom(Val, _) -> Val.

View File

@ -79,7 +79,7 @@ init(_) ->
handle_call({add_child, ConfKeyPath, HandlerName}, _From, handle_call({add_child, ConfKeyPath, HandlerName}, _From,
State = #{handlers := Handlers}) -> State = #{handlers := Handlers}) ->
{reply, ok, State#{handlers => {reply, ok, State#{handlers =>
emqx_config:deep_put(ConfKeyPath, Handlers, #{?MOD => HandlerName})}}; emqx_map_lib:deep_put(ConfKeyPath, Handlers, #{?MOD => HandlerName})}};
handle_call({update_config, ConfKeyPath, UpdateReq, RawConf}, _From, handle_call({update_config, ConfKeyPath, UpdateReq, RawConf}, _From,
#{handlers := Handlers} = State) -> #{handlers := Handlers} = State) ->
@ -161,7 +161,7 @@ save_configs(RootKeys, RawConf) ->
save_config_to_emqx(Conf, RawConf) -> save_config_to_emqx(Conf, RawConf) ->
?LOG(debug, "set config: ~p", [Conf]), ?LOG(debug, "set config: ~p", [Conf]),
emqx_config:put(emqx_config:unsafe_atom_key_map(Conf)), emqx_config:put(emqx_map_lib:unsafe_atom_key_map(Conf)),
emqx_config:put_raw(RawConf). emqx_config:put_raw(RawConf).
save_config_to_disk(RootKeys, Conf) -> save_config_to_disk(RootKeys, Conf) ->

View File

@ -88,7 +88,7 @@ do_start_listener(ZoneName, ListenerName, #{type := ws, bind := ListenOn} = Opts
esockd_opts(Opts0) -> esockd_opts(Opts0) ->
Opts1 = maps:with([acceptors, max_connections, proxy_protocol, proxy_protocol_timeout], Opts0), Opts1 = maps:with([acceptors, max_connections, proxy_protocol, proxy_protocol_timeout], Opts0),
Opts2 = case emqx_config:deep_get([rate_limit, max_conn_rate], Opts0) of Opts2 = case emqx_map_lib:deep_get([rate_limit, max_conn_rate], Opts0) of
infinity -> Opts1; infinity -> Opts1;
Rate -> Opts1#{max_conn_rate => Rate} Rate -> Opts1#{max_conn_rate => Rate}
end, end,
@ -204,4 +204,4 @@ tcp_opts(Opts) ->
maps:get(tcp, Opts, #{}))). maps:get(tcp, Opts, #{}))).
is_ssl(Opts) -> is_ssl(Opts) ->
emqx_config:deep_get([ssl, enable], Opts, false). emqx_map_lib:deep_get([ssl, enable], Opts, false).

View File

@ -0,0 +1,75 @@
%%--------------------------------------------------------------------
%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%--------------------------------------------------------------------
-module(emqx_map_lib).
-export([ deep_get/2
, deep_get/3
, deep_put/3
, safe_atom_key_map/1
, unsafe_atom_key_map/1
]).
-export_type([config_key/0, config_key_path/0]).
-type config_key() :: atom() | binary().
-type config_key_path() :: [config_key()].
%%-----------------------------------------------------------------
-spec deep_get(config_key_path(), map()) -> term().
deep_get(ConfKeyPath, Map) ->
do_deep_get(ConfKeyPath, Map, fun(KeyPath, Data) ->
error({not_found, KeyPath, Data}) end).
-spec deep_get(config_key_path(), map(), term()) -> term().
deep_get(ConfKeyPath, Map, Default) ->
do_deep_get(ConfKeyPath, Map, fun(_, _) -> Default end).
-spec deep_put(config_key_path(), map(), term()) -> map().
deep_put([], Map, Config) when is_map(Map) ->
Config;
deep_put([Key | KeyPath], Map, Config) ->
SubMap = deep_put(KeyPath, maps:get(Key, Map, #{}), Config),
Map#{Key => SubMap}.
unsafe_atom_key_map(Map) ->
covert_keys_to_atom(Map, fun(K) -> binary_to_atom(K, utf8) end).
safe_atom_key_map(Map) ->
covert_keys_to_atom(Map, fun(K) -> binary_to_existing_atom(K, utf8) end).
%%---------------------------------------------------------------------------
-spec do_deep_get(config_key_path(), map(), fun((config_key(), term()) -> any())) -> term().
do_deep_get([], Map, _) ->
Map;
do_deep_get([Key | KeyPath], Map, OnNotFound) when is_map(Map) ->
case maps:find(Key, Map) of
{ok, SubMap} -> do_deep_get(KeyPath, SubMap, OnNotFound);
error -> OnNotFound(Key, Map)
end;
do_deep_get([Key | _KeyPath], Data, OnNotFound) ->
OnNotFound(Key, Data).
covert_keys_to_atom(BinKeyMap, Conv) when is_map(BinKeyMap) ->
maps:fold(
fun(K, V, Acc) when is_binary(K) ->
Acc#{Conv(K) => covert_keys_to_atom(V, Conv)};
(K, V, Acc) when is_atom(K) ->
%% richmap keys
Acc#{K => covert_keys_to_atom(V, Conv)}
end, #{}, BinKeyMap);
covert_keys_to_atom(ListV, Conv) when is_list(ListV) ->
[covert_keys_to_atom(V, Conv) || V <- ListV];
covert_keys_to_atom(Val, _) -> Val.