fix(emqx_map_lib): ignore non-number non-map values
This commit is contained in:
parent
3524fb6994
commit
5deb0c4878
|
@ -269,17 +269,50 @@ error_type_two_maps(M1, _M2) ->
|
|||
|
||||
%% @doc Sum-merge map values.
|
||||
%% For bad merges, ErrorLogger is called to log the key, and value in M2 is ignored.
|
||||
best_effort_recursive_sum(M1, M2, ErrorLogger) ->
|
||||
best_effort_recursive_sum(M10, M20, ErrorLogger) ->
|
||||
FilterF = fun(K, V) ->
|
||||
case erlang:is_number(V) of
|
||||
true ->
|
||||
true;
|
||||
false ->
|
||||
ErrorLogger(#{failed_to_merge => K, bad_value => V}),
|
||||
false
|
||||
end
|
||||
end,
|
||||
M1 = deep_filter(M10, FilterF),
|
||||
M2 = deep_filter(M20, FilterF),
|
||||
do_best_effort_recursive_sum(M1, M2, ErrorLogger).
|
||||
|
||||
do_best_effort_recursive_sum(M1, M2, ErrorLogger) ->
|
||||
F =
|
||||
fun(Key, V1, V2) ->
|
||||
case {erlang:is_map(V1), erlang:is_map(V2)} of
|
||||
{true, true} ->
|
||||
best_effort_recursive_sum(V1, V2, ErrorLogger);
|
||||
{false, false} when is_number(V1) andalso is_number(V2) ->
|
||||
V1 + V2;
|
||||
_ ->
|
||||
ErrorLogger(#{failed_to_merge => Key}),
|
||||
V1
|
||||
do_best_effort_recursive_sum(V1, V2, ErrorLogger);
|
||||
{true, false} ->
|
||||
ErrorLogger(#{failed_to_merge => Key, bad_value => V2}),
|
||||
do_best_effort_recursive_sum(V1, #{}, ErrorLogger);
|
||||
{false, true} ->
|
||||
ErrorLogger(#{failed_to_merge => Key, bad_value => V1}),
|
||||
do_best_effort_recursive_sum(V2, #{}, ErrorLogger);
|
||||
{false, false} ->
|
||||
true = is_number(V1),
|
||||
true = is_number(V2),
|
||||
V1 + V2
|
||||
end
|
||||
end,
|
||||
merge_with(F, M1, M2).
|
||||
|
||||
deep_filter(M, F) when is_map(M) ->
|
||||
%% maps:filtermap is not available before OTP 24
|
||||
maps:from_list(
|
||||
lists:filtermap(
|
||||
fun
|
||||
({K, V}) when is_map(V) ->
|
||||
{true, {K, deep_filter(V, F)}};
|
||||
({K, V}) ->
|
||||
F(K, V) andalso {true, {K, V}}
|
||||
end,
|
||||
maps:to_list(M)
|
||||
)
|
||||
).
|
||||
|
|
|
@ -49,8 +49,62 @@ best_effort_recursive_sum_test_() ->
|
|||
),
|
||||
receive
|
||||
{log, Log} ->
|
||||
?assertEqual(#{failed_to_merge => bar}, Log)
|
||||
?assertEqual(#{failed_to_merge => bar, bad_value => bar}, Log)
|
||||
after 1000 -> error(timeout)
|
||||
end
|
||||
end
|
||||
end,
|
||||
?_assertEqual(
|
||||
#{},
|
||||
emqx_map_lib:best_effort_recursive_sum(
|
||||
#{foo => foo}, #{foo => bar}, DummyLogger
|
||||
)
|
||||
),
|
||||
?_assertEqual(
|
||||
#{foo => 1},
|
||||
emqx_map_lib:best_effort_recursive_sum(
|
||||
#{foo => 1}, #{foo => bar}, DummyLogger
|
||||
)
|
||||
),
|
||||
?_assertEqual(
|
||||
#{foo => 1},
|
||||
emqx_map_lib:best_effort_recursive_sum(
|
||||
#{foo => bar}, #{foo => 1}, DummyLogger
|
||||
)
|
||||
),
|
||||
?_assertEqual(
|
||||
#{foo => #{bar => 1}},
|
||||
emqx_map_lib:best_effort_recursive_sum(
|
||||
#{foo => #{bar => 1}}, #{foo => 1}, DummyLogger
|
||||
)
|
||||
),
|
||||
?_assertEqual(
|
||||
#{foo => #{bar => 1}},
|
||||
emqx_map_lib:best_effort_recursive_sum(
|
||||
#{foo => 1}, #{foo => #{bar => 1}}, DummyLogger
|
||||
)
|
||||
),
|
||||
?_assertEqual(
|
||||
#{foo => #{bar => 1}},
|
||||
emqx_map_lib:best_effort_recursive_sum(
|
||||
#{foo => 1, bar => ignored}, #{foo => #{bar => 1}}, DummyLogger
|
||||
)
|
||||
),
|
||||
?_assertEqual(
|
||||
#{foo => #{bar => 2}, bar => #{foo => 1}},
|
||||
emqx_map_lib:best_effort_recursive_sum(
|
||||
#{foo => 1, bar => #{foo => 1}}, #{foo => #{bar => 2}, bar => 2}, DummyLogger
|
||||
)
|
||||
),
|
||||
?_assertEqual(
|
||||
#{foo => #{bar => 2}, bar => #{foo => 1}},
|
||||
emqx_map_lib:best_effort_recursive_sum(
|
||||
#{foo => #{bar => 2}, bar => 2}, #{foo => 1, bar => #{foo => 1}}, DummyLogger
|
||||
)
|
||||
),
|
||||
?_assertEqual(
|
||||
#{foo => #{bar => #{}}},
|
||||
emqx_map_lib:best_effort_recursive_sum(
|
||||
#{foo => #{bar => #{foo => []}}}, #{foo => 1}, DummyLogger
|
||||
)
|
||||
)
|
||||
].
|
||||
|
|
Loading…
Reference in New Issue