Sfoglia il codice sorgente

fix(client_api): correctly apply conn_state selector in search queries

Ilya Averyanov 1 anno fa
parent
commit
09e1375d48

+ 27 - 13
apps/emqx_management/src/emqx_mgmt_api_clients.erl

@@ -28,6 +28,8 @@
 -include_lib("emqx_utils/include/emqx_utils_api.hrl").
 -include_lib("emqx_utils/include/emqx_utils_api.hrl").
 -include_lib("emqx/include/emqx_durable_session_metadata.hrl").
 -include_lib("emqx/include/emqx_durable_session_metadata.hrl").
 
 
+-include_lib("snabbkaffe/include/snabbkaffe.hrl").
+
 -include("emqx_mgmt.hrl").
 -include("emqx_mgmt.hrl").
 
 
 %% API
 %% API
@@ -1069,7 +1071,7 @@ run_filters(Rows, QString0) ->
     FuzzyFilterFn = fuzzy_filter_fun(FuzzyQString),
     FuzzyFilterFn = fuzzy_filter_fun(FuzzyQString),
     lists:filter(
     lists:filter(
         fun(Row) ->
         fun(Row) ->
-            does_row_match_query(Row, QString) andalso
+            does_offline_row_match_query(Row, QString) andalso
                 does_row_match_fuzzy_filter(Row, FuzzyFilterFn)
                 does_row_match_fuzzy_filter(Row, FuzzyFilterFn)
         end,
         end,
         Rows
         Rows
@@ -1722,45 +1724,57 @@ ms(created_at, X) ->
 %%
 %%
 %% These functions are used with clients_v2 API.
 %% These functions are used with clients_v2 API.
 
 
-does_chan_info_match({ip_address, '=:=', IpAddress}, #{conninfo := #{peername := {IpAddress, _}}}) ->
+does_offline_chan_info_match({ip_address, '=:=', IpAddress}, #{
+    conninfo := #{peername := {IpAddress, _}}
+}) ->
     true;
     true;
-does_chan_info_match({conn_state, '=:=', State}, #{conn_state := State}) ->
+%% This matchers match only offline clients, because online clients are listed directly from
+%% channel manager's ETS tables. So we succeed here only if offline conn_state is requested.
+does_offline_chan_info_match({conn_state, '=:=', disconnected}, _) ->
     true;
     true;
-does_chan_info_match({clean_start, '=:=', CleanStart}, #{conninfo := #{clean_start := CleanStart}}) ->
+does_offline_chan_info_match({conn_state, '=:=', _}, _) ->
+    false;
+does_offline_chan_info_match({clean_start, '=:=', CleanStart}, #{
+    conninfo := #{clean_start := CleanStart}
+}) ->
     true;
     true;
-does_chan_info_match({proto_ver, '=:=', ProtoVer}, #{conninfo := #{proto_ver := ProtoVer}}) ->
+does_offline_chan_info_match({proto_ver, '=:=', ProtoVer}, #{conninfo := #{proto_ver := ProtoVer}}) ->
     true;
     true;
-does_chan_info_match({connected_at, '>=', ConnectedAtFrom}, #{
+does_offline_chan_info_match({connected_at, '>=', ConnectedAtFrom}, #{
     conninfo := #{connected_at := ConnectedAt}
     conninfo := #{connected_at := ConnectedAt}
 }) when
 }) when
     ConnectedAt >= ConnectedAtFrom
     ConnectedAt >= ConnectedAtFrom
 ->
 ->
     true;
     true;
-does_chan_info_match({connected_at, '=<', ConnectedAtTo}, #{
+does_offline_chan_info_match({connected_at, '=<', ConnectedAtTo}, #{
     conninfo := #{connected_at := ConnectedAt}
     conninfo := #{connected_at := ConnectedAt}
 }) when
 }) when
     ConnectedAt =< ConnectedAtTo
     ConnectedAt =< ConnectedAtTo
 ->
 ->
     true;
     true;
-does_chan_info_match({created_at, '>=', CreatedAtFrom}, #{session := #{created_at := CreatedAt}}) when
+does_offline_chan_info_match({created_at, '>=', CreatedAtFrom}, #{
+    session := #{created_at := CreatedAt}
+}) when
     CreatedAt >= CreatedAtFrom
     CreatedAt >= CreatedAtFrom
 ->
 ->
     true;
     true;
-does_chan_info_match({created_at, '=<', CreatedAtTo}, #{session := #{created_at := CreatedAt}}) when
+does_offline_chan_info_match({created_at, '=<', CreatedAtTo}, #{
+    session := #{created_at := CreatedAt}
+}) when
     CreatedAt =< CreatedAtTo
     CreatedAt =< CreatedAtTo
 ->
 ->
     true;
     true;
-does_chan_info_match(_, _) ->
+does_offline_chan_info_match(_, _) ->
     false.
     false.
 
 
-does_row_match_query(
+does_offline_row_match_query(
     {_Id, #{metadata := #{offline_info := #{chan_info := ChanInfo}}}}, CompiledQueryString
     {_Id, #{metadata := #{offline_info := #{chan_info := ChanInfo}}}}, CompiledQueryString
 ) ->
 ) ->
     lists:all(
     lists:all(
-        fun(FieldQuery) -> does_chan_info_match(FieldQuery, ChanInfo) end,
+        fun(FieldQuery) -> does_offline_chan_info_match(FieldQuery, ChanInfo) end,
         CompiledQueryString
         CompiledQueryString
     );
     );
-does_row_match_query(_, _) ->
+does_offline_row_match_query(_, _) ->
     false.
     false.
 
 
 %%--------------------------------------------------------------------
 %%--------------------------------------------------------------------

+ 15 - 0
apps/emqx_management/test/emqx_mgmt_api_clients_SUITE.erl

@@ -1953,6 +1953,21 @@ t_list_clients_v2_regular_filters(Config) ->
                 Res2
                 Res2
             ),
             ),
 
 
+            QueryParams3 = [
+                {"limit", "100"},
+                {"conn_state", "connected"}
+            ],
+            Res3 = list_all_v2(QueryParams3, Config),
+            ?assertMatch(
+                [
+                    #{
+                        <<"data">> := [],
+                        <<"meta">> := #{<<"count">> := 0}
+                    }
+                ],
+                Res3
+            ),
+
             ?tp(warning, destroy_session, #{clientid => ClientId1}),
             ?tp(warning, destroy_session, #{clientid => ClientId1}),
             ok = erpc:call(N1, emqx_persistent_session_ds, destroy_session, [ClientId1])
             ok = erpc:call(N1, emqx_persistent_session_ds, destroy_session, [ClientId1])
         end,
         end,

+ 1 - 0
changes/ce/fix-14151.en.md

@@ -0,0 +1 @@
+In `/clients_v2` API, correctly handle `conn_state` filtering selector for offline clients with durable sessions. Previously, offline clients with durable sessions could be selected with `conn_state=connected` selector value.