This is an automated email from the ASF dual-hosted git repository. chewbranca pushed a commit to branch couch-stats-resource-tracker-v3-rebase-http in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit a95d5e434edf7be87eb721e222c71d27e4877b24 Author: Russell Branca <[email protected]> AuthorDate: Tue Jun 24 20:22:36 2025 -0700 make erlfmt-format --- src/chttpd/src/chttpd_node.erl | 10 ++++- src/couch_stats/src/csrt.erl | 82 ++++++++++++++++++++++++-------------- src/couch_stats/src/csrt_httpd.erl | 15 ++++--- src/couch_stats/src/csrt_query.erl | 52 ++++++++++++++---------- 4 files changed, 102 insertions(+), 57 deletions(-) diff --git a/src/chttpd/src/chttpd_node.erl b/src/chttpd/src/chttpd_node.erl index f08530ce1..3869b279a 100644 --- a/src/chttpd/src/chttpd_node.erl +++ b/src/chttpd/src/chttpd_node.erl @@ -178,7 +178,11 @@ handle_node_req(#httpd{method = 'POST', path_parts = [_, Node, <<"_restart">>]} send_json(Req, 200, {[{ok, true}]}); handle_node_req(#httpd{path_parts = [_, _Node, <<"_restart">>]} = Req) -> send_method_not_allowed(Req, "POST"); -handle_node_req(#httpd{method = 'GET', path_parts = [_, Node, <<"_active_resources">>, <<"_match">>, MatcherName]} = Req) -> +handle_node_req( + #httpd{ + method = 'GET', path_parts = [_, Node, <<"_active_resources">>, <<"_match">>, MatcherName] + } = Req +) -> case call_node(Node, csrt, query_matcher, [binary_to_list(MatcherName)]) of {ok, Rctxs} -> send_json(Req, 200, Rctxs); @@ -187,7 +191,9 @@ handle_node_req(#httpd{method = 'GET', path_parts = [_, Node, <<"_active_resourc {error, Reason} -> throw({bad_request, Reason}) end; -handle_node_req(#httpd{method = _, path_parts = [_, _Node, <<"_active_resources">>, <<"_match">> | _]} = Req) -> +handle_node_req( + #httpd{method = _, path_parts = [_, _Node, <<"_active_resources">>, <<"_match">> | _]} = Req +) -> send_method_not_allowed(Req, "GET"); handle_node_req(#httpd{ path_parts = [_, Node | PathParts], diff --git a/src/couch_stats/src/csrt.erl b/src/couch_stats/src/csrt.erl index e288a1ad4..01a99b40a 100644 --- a/src/couch_stats/src/csrt.erl +++ b/src/couch_stats/src/csrt.erl @@ -121,32 +121,53 @@ rpc(FName, Args) when is_atom(FName) andalso is_list(Args) -> {Results, lists:usort(Errors), BadNodes}. split_response(Resp) -> - lists:foldl(fun(Message, {Results, Errors}) -> - case Message of - {badrpc, _} = E -> - {Results, [E | Errors]}; - Result -> - {[Result | Results], Errors} - end - end, {[], []}, Resp). - -call({active, []}) -> {node(), active()}; -call({active, [json]}) -> {node(), active(json)}; -call({active_coordinators, []}) -> {node(), active_coordinators()}; -call({active_coordinators, [json]}) -> {node(), active_coordinators(json)}; -call({active_workers, []}) -> {node(), active_workers()}; -call({active_workers, [json]}) -> {node(), active_workers(json)}; -call({count_by, [Key]}) -> {node(), count_by(Key)}; -call({find_by_nonce, [Nonce]}) -> {node(), find_by_nonce(Nonce)}; -call({find_by_pid, [Pid]}) -> {node(), find_by_pid(Pid)}; -call({find_by_pidref, [PidRef]}) -> {node(), find_by_pidref(PidRef)}; -call({find_workers_by_pidref, [PidRef]}) -> {node(), find_workers_by_pidref(PidRef)}; -call({group_by, [Key, Val]}) -> {node(), group_by(Key, Val)}; -call({group_by, [Key, Val, Agg]}) -> {node(), group_by(Key, Val, Agg)}; -call({sorted, [Map]}) -> {node(), sorted(Map)}; -call({sorted_by, [Key]}) -> {node(), sorted_by(Key)}; -call({sorted_by, [Key, Val]}) -> {node(), sorted_by(Key, Val)}; -call({sorted_by, [Key, Val, Agg]}) -> {node(), sorted_by(Key, Val, Agg)}; + lists:foldl( + fun(Message, {Results, Errors}) -> + case Message of + {badrpc, _} = E -> + {Results, [E | Errors]}; + Result -> + {[Result | Results], Errors} + end + end, + {[], []}, + Resp + ). + +call({active, []}) -> + {node(), active()}; +call({active, [json]}) -> + {node(), active(json)}; +call({active_coordinators, []}) -> + {node(), active_coordinators()}; +call({active_coordinators, [json]}) -> + {node(), active_coordinators(json)}; +call({active_workers, []}) -> + {node(), active_workers()}; +call({active_workers, [json]}) -> + {node(), active_workers(json)}; +call({count_by, [Key]}) -> + {node(), count_by(Key)}; +call({find_by_nonce, [Nonce]}) -> + {node(), find_by_nonce(Nonce)}; +call({find_by_pid, [Pid]}) -> + {node(), find_by_pid(Pid)}; +call({find_by_pidref, [PidRef]}) -> + {node(), find_by_pidref(PidRef)}; +call({find_workers_by_pidref, [PidRef]}) -> + {node(), find_workers_by_pidref(PidRef)}; +call({group_by, [Key, Val]}) -> + {node(), group_by(Key, Val)}; +call({group_by, [Key, Val, Agg]}) -> + {node(), group_by(Key, Val, Agg)}; +call({sorted, [Map]}) -> + {node(), sorted(Map)}; +call({sorted_by, [Key]}) -> + {node(), sorted_by(Key)}; +call({sorted_by, [Key, Val]}) -> + {node(), sorted_by(Key, Val)}; +call({sorted_by, [Key, Val, Agg]}) -> + {node(), sorted_by(Key, Val, Agg)}; call({FunName, Args}) -> FunNameBin = atom_to_binary(FunName), ArityBin = integer_to_binary(length(Args)), @@ -485,17 +506,20 @@ pid_ref_attrs(AttrName) -> proc_window(AttrName, Num, Time) -> csrt_logger:proc_window(AttrName, Num, Time). --spec query_matcher(MatcherName :: matcher_name()) -> {ok, query_result()} +-spec query_matcher(MatcherName :: matcher_name()) -> + {ok, query_result()} | {error, any()}. query_matcher(MatcherName) -> csrt_query:query_matcher(MatcherName). --spec query_matcher(MatcherName :: matcher_name(), Limit :: pos_integer()) -> {ok, query_result()} +-spec query_matcher(MatcherName :: matcher_name(), Limit :: pos_integer()) -> + {ok, query_result()} | {error, any()}. query_matcher(MatcherName, Limit) -> csrt_query:query_matcher(MatcherName, Limit). --spec query(Keys :: string() | [string()], Options :: query_options()) -> {ok, query_result()} +-spec query(Keys :: string() | [string()], Options :: query_options()) -> + {ok, query_result()} | {error, any()}. query(Keys) -> csrt_query:query(Keys). diff --git a/src/couch_stats/src/csrt_httpd.erl b/src/couch_stats/src/csrt_httpd.erl index e4eb13fd2..d9eb6376b 100644 --- a/src/couch_stats/src/csrt_httpd.erl +++ b/src/couch_stats/src/csrt_httpd.erl @@ -37,7 +37,9 @@ resp_to_json([], Acc) -> % %% TODO: incorporate Bad responses % Resp = rpc_to_json(csrt:rpc(active, [json])), % send_json(Req, Resp); -handle_resource_status_req(#httpd{method = 'POST', path_parts = [<<"_active_resources">>, <<"_match">>, MatcherName]} = Req) -> +handle_resource_status_req( + #httpd{method = 'POST', path_parts = [<<"_active_resources">>, <<"_match">>, MatcherName]} = Req +) -> chttpd:validate_ctype(Req, "application/json"), {JsonProps} = chttpd:json_body_obj(Req), GroupBy = couch_util:get_value(<<"group_by">>, JsonProps), @@ -57,7 +59,6 @@ handle_resource_status_req(#httpd{method = 'POST', path_parts = [<<"_active_reso handle_resource_status_req(#httpd{path_parts = [<<"_active_resources">>]} = Req) -> ok = chttpd:verify_is_server_admin(Req), send_method_not_allowed(Req, "GET,HEAD"); - handle_resource_status_req(Req) -> ok = chttpd:verify_is_server_admin(Req), send_method_not_allowed(Req, "GET,HEAD,POST"). @@ -129,8 +130,10 @@ query_matcher(MatcherName, AggregationKey, CounterKey) -> csrt_query:query_matcher(Matcher, AggregationKey, CounterKey) end. --spec to_key(BinKey :: binary() | string()) -> Key :: rctx_field() - | throw({bad_request, Reason :: binary()}). +-spec to_key(BinKey :: binary() | string()) -> + Key :: + rctx_field() + | throw({bad_request, Reason :: binary()}). to_key(<<"pid_ref">>) -> pid_ref; to_key(<<"nonce">>) -> nonce; @@ -148,7 +151,8 @@ to_key(<<"get_kv_node">>) -> get_kv_node; to_key(<<"get_kp_node">>) -> get_kp_node; to_key(Other) when is_binary(Other) -> throw({bad_request, <<"Invalid key '", Other/binary, "'">>}). --spec parse_key(Keys :: binary() | [binary()]) -> [rctx_field()] +-spec parse_key(Keys :: binary() | [binary()]) -> + [rctx_field()] | throw({bad_request, Reason :: binary()}). parse_key(Keys) when is_list(Keys) -> @@ -162,4 +166,3 @@ parse_key([BinKey | Rest], Keys) -> parse_key(Rest, [to_key(BinKey) | Keys]); parse_key([], Keys) -> lists:reverse(Keys). - diff --git a/src/couch_stats/src/csrt_query.erl b/src/couch_stats/src/csrt_query.erl index 717b44de7..4feb7e9b1 100644 --- a/src/couch_stats/src/csrt_query.erl +++ b/src/couch_stats/src/csrt_query.erl @@ -173,12 +173,13 @@ group_by(Matcher, KeyFun, ValFun, AggFun, Limit) -> end; false -> throw({limit, Acc}) - end + end end, try {ok, ets:foldl(FoldFun, #{}, ?CSRT_ETS)} - catch throw:{limit, Acc} -> - {limit, Acc} + catch + throw:{limit, Acc} -> + {limit, Acc} end. maybe_match(_Ele, undefined) -> @@ -194,7 +195,7 @@ maybe_match(Ele, {_, MS}) -> % we store ordered elements in ascending order seq = [] :: list(pos_integer()), % we rely on erlang sorting order where `number < atom` - min = infinite :: infinite | pos_integer(), + min = infinite :: infinite | pos_integer(), max = 0 :: pos_integer(), size = 0 :: non_neg_integer(), % capacity cannot be less than 1 @@ -209,7 +210,9 @@ new_topK(K) when K >= 1 -> update_topK(_Key, Value, #topK{size = S, capacity = S, min = Min} = Top) when Value < Min -> Top#topK{min = Value}; % when we are at capacity evict smallest value -update_topK(Key, Value, #topK{size = S, capacity = S, max = Max, seq = Seq} = Top) when Value > Max -> +update_topK(Key, Value, #topK{size = S, capacity = S, max = Max, seq = Seq} = Top) when + Value > Max +-> % capacity cannot be less than 1, so we can avoid handling the case when Seq is empty [_ | Truncated] = Seq, Top#topK{max = Value, seq = lists:keysort(2, [{Key, Value} | Truncated])}; @@ -246,12 +249,14 @@ sort_by(KeyFun, ValFun, AggFun) -> to_json_list(List) when is_list(List) -> lists:map(fun csrt_util:to_json/1, List). --spec query_matcher(MatcherName :: string()) -> {ok, query_result()} +-spec query_matcher(MatcherName :: string()) -> + {ok, query_result()} | {error, any()}. -query_matcher(MatcherName) when is_list(MatcherName) -> +query_matcher(MatcherName) when is_list(MatcherName) -> query_matcher(MatcherName, query_limit()). --spec query_matcher(MatcherName :: matcher_name(), Limit :: pos_integer()) -> {ok, query_result()} +-spec query_matcher(MatcherName :: matcher_name(), Limit :: pos_integer()) -> + {ok, query_result()} | {error, any()}. query_matcher(MatcherName, Limit) when is_list(MatcherName) andalso is_integer(Limit) -> case csrt_logger:get_matcher(MatcherName) of @@ -261,38 +266,45 @@ query_matcher(MatcherName, Limit) when is_list(MatcherName) andalso is_integer(L query_matcher_rows(Matcher, Limit) end. --spec query_matcher_rows(Matcher :: matcher()) -> {ok, query_result()} +-spec query_matcher_rows(Matcher :: matcher()) -> + {ok, query_result()} | {error, any()}. query_matcher_rows(Matcher) -> query_matcher_rows(Matcher, query_limit()). --spec query_matcher_rows(Matcher :: matcher(), Limit :: pos_integer()) -> {ok, query_result()} +-spec query_matcher_rows(Matcher :: matcher(), Limit :: pos_integer()) -> + {ok, query_result()} | {error, any()}. -query_matcher_rows({MSpec, _CompMSpec}, Limit) when is_list(MSpec) andalso is_integer(Limit) andalso Limit >= 1 -> +query_matcher_rows({MSpec, _CompMSpec}, Limit) when + is_list(MSpec) andalso is_integer(Limit) andalso Limit >= 1 +-> try %% ets:select/* takes match_spec(), not comp_match_spec() %% use ets:select/3 to constrain to Limit rows, but we need to handle %% the continuation() style return type compared with ets:select/2. - Rctxs = case ets:select(?CSRT_ETS, MSpec, Limit) of - {Rctxs0, _Continuation} -> - Rctxs0; - %% Handle '$end_of_table' - _ -> - [] - end, + Rctxs = + case ets:select(?CSRT_ETS, MSpec, Limit) of + {Rctxs0, _Continuation} -> + Rctxs0; + %% Handle '$end_of_table' + _ -> + [] + end, {ok, to_json_list(Rctxs)} catch _:_ = Error -> {error, Error} end. --spec query(Keys :: string() | [string()]) -> {ok, query_result()} +-spec query(Keys :: string() | [string()]) -> + {ok, query_result()} | {error, any()}. %% #{{<<"adm">>,<<"bench-yktbb3as46rzffea">>} => 2} query(Keys) -> query(Keys, []). --spec query(Keys :: string() | [string()], Options :: query_options()) -> {ok, query_result()} +-spec query(Keys :: string() | [string()], Options :: query_options()) -> + {ok, query_result()} | {error, any()}. %% #{{<<"adm">>,<<"bench-yktbb3as46rzffea">>} => 2} query(_Keys, _Options) ->
