Ver código fonte

fix(emqx_mgmt): handle client shutdown errors in call_client

The client process may be shutdown normally during/shortly before the call.
Serge Tupchii 1 ano atrás
pai
commit
ed0b5ac939

+ 11 - 1
apps/emqx_management/src/emqx_mgmt.erl

@@ -514,7 +514,7 @@ do_call_client(ClientId, Req) ->
             Pid = lists:last(Pids),
             case emqx_cm:get_chan_info(ClientId, Pid) of
                 #{conninfo := #{conn_mod := ConnMod}} ->
-                    erlang:apply(ConnMod, call, [Pid, Req]);
+                    call_conn(ConnMod, Pid, Req);
                 undefined ->
                     {error, not_found}
             end
@@ -703,3 +703,13 @@ check_results(Results) ->
 
 default_row_limit() ->
     ?DEFAULT_ROW_LIMIT.
+
+call_conn(ConnMod, Pid, Req) ->
+    try
+        erlang:apply(ConnMod, call, [Pid, Req])
+    catch
+        exit:R when R =:= shutdown; R =:= normal ->
+            {error, shutdown};
+        exit:{R, _} when R =:= shutdown; R =:= noproc ->
+            {error, shutdown}
+    end.

+ 8 - 1
apps/emqx_management/src/emqx_mgmt_api_clients.erl

@@ -90,6 +90,11 @@
     message => <<"Client ID not found">>
 }).
 
+-define(CLIENT_SHUTDOWN, #{
+    code => 'CLIENT_SHUTDOWN',
+    message => <<"Client connection has been shutdown">>
+}).
+
 namespace() -> undefined.
 
 api_spec() ->
@@ -941,7 +946,7 @@ client_msgs_schema(OpId, Desc, ContExample, RespSchema) ->
                         ['INVALID_PARAMETER'], <<"Invalid parameters">>
                     ),
                 404 => emqx_dashboard_swagger:error_codes(
-                    ['CLIENTID_NOT_FOUND'], <<"Client ID not found">>
+                    ['CLIENTID_NOT_FOUND', 'CLIENT_SHUTDOWN'], <<"Client ID not found">>
                 ),
                 ?NOT_IMPLEMENTED => emqx_dashboard_swagger:error_codes(
                     ['NOT_IMPLEMENTED'], <<"API not implemented">>
@@ -1220,6 +1225,8 @@ list_client_msgs(MsgType, ClientID, QString) ->
             case emqx_mgmt:list_client_msgs(MsgType, ClientID, PagerParams) of
                 {error, not_found} ->
                     {404, ?CLIENTID_NOT_FOUND};
+                {error, shutdown} ->
+                    {404, ?CLIENT_SHUTDOWN};
                 {error, not_implemented} ->
                     {?NOT_IMPLEMENTED, #{
                         code => 'NOT_IMPLEMENTED',