From 068421d0e14d50ef35c9f7fe3eb92311586a7513 Mon Sep 17 00:00:00 2001 From: Zhongwen Deng Date: Sat, 7 May 2022 16:48:03 +0800 Subject: [PATCH] feat: don't dispatch requests until dispatch is ready --- apps/emqx/src/emqx_tls_lib.erl | 28 ++++++++----------- apps/emqx_dashboard/src/emqx_dashboard.erl | 2 +- .../src/emqx_dashboard_listener.erl | 17 +++++++---- .../src/emqx_dashboard_middleware.erl | 20 +++++++++++++ 4 files changed, 44 insertions(+), 23 deletions(-) diff --git a/apps/emqx/src/emqx_tls_lib.erl b/apps/emqx/src/emqx_tls_lib.erl index 17aaad74e..f59a67f4a 100644 --- a/apps/emqx/src/emqx_tls_lib.erl +++ b/apps/emqx/src/emqx_tls_lib.erl @@ -27,9 +27,6 @@ all_ciphers/0 ]). --compile(export_all). --compile(nowarn_export_all). - %% SSL files -export([ ensure_ssl_files/2, @@ -219,19 +216,18 @@ default_versions(_) -> %% Deduplicate a list without re-ordering the elements. dedup([]) -> []; -dedup(List) -> - lists:reverse( - lists:foldl( - fun(L, Acc) -> - case lists:member(L, Acc) of - false -> [L | Acc]; - true -> Acc - end - end, - [], - List - ) - ). +dedup(List0) -> + List = lists:foldl( + fun(L, Acc) -> + case lists:member(L, Acc) of + false -> [L | Acc]; + true -> Acc + end + end, + [], + List0 + ), + lists:reverse(List). %% parse comma separated tls version strings parse_versions(Versions) -> diff --git a/apps/emqx_dashboard/src/emqx_dashboard.erl b/apps/emqx_dashboard/src/emqx_dashboard.erl index 6c50ca0c7..974d438be 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard.erl @@ -81,7 +81,7 @@ start_listeners(Listeners) -> security => [#{'basicAuth' => []}, #{'bearerAuth' => []}], swagger_global_spec => GlobalSpec, dispatch => Dispatch, - middlewares => [cowboy_router, ?EMQX_MIDDLE, cowboy_handler] + middlewares => [?EMQX_MIDDLE, cowboy_router, cowboy_handler] }, Res = lists:foldl( diff --git a/apps/emqx_dashboard/src/emqx_dashboard_listener.erl b/apps/emqx_dashboard/src/emqx_dashboard_listener.erl index db06d42ab..31f309f9a 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_listener.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_listener.erl @@ -25,7 +25,7 @@ -behaviour(gen_server). --export([start_link/0]). +-export([start_link/0, is_ready/0]). -export([ init/1, @@ -37,29 +37,34 @@ code_change/3 ]). +is_ready() -> + ready =:= gen_server:call(?MODULE, get_state, 10000). + start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). init([]) -> erlang:process_flag(trap_exit, true), ok = add_handler(), - {ok, #{}, {continue, regenerate_dispatch}}. + {ok, undefined, {continue, regenerate_dispatch}}. -handle_continue(regenerate_dispatch, State) -> +handle_continue(regenerate_dispatch, _State) -> regenerate_minirest_dispatch(), - {noreply, State, hibernate}. + {noreply, ready, hibernate}. +handle_call(get_state, _From, State) -> + {reply, State, State, hibernate}; handle_call(_Request, _From, State) -> {reply, ok, State, hibernate}. handle_cast(_Request, State) -> {noreply, State, hibernate}. -handle_info({update_listeners, OldListeners, NewListeners}, State) -> +handle_info({update_listeners, OldListeners, NewListeners}, _State) -> ok = emqx_dashboard:stop_listeners(OldListeners), ok = emqx_dashboard:start_listeners(NewListeners), regenerate_minirest_dispatch(), - {noreply, State, hibernate}; + {noreply, ready, hibernate}; handle_info(_Info, State) -> {noreply, State, hibernate}. diff --git a/apps/emqx_dashboard/src/emqx_dashboard_middleware.erl b/apps/emqx_dashboard/src/emqx_dashboard_middleware.erl index 77b6dbdd0..b07ab21f4 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_middleware.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_middleware.erl @@ -21,6 +21,7 @@ -export([execute/2]). execute(Req, Env) -> + waiting_dispatch_ready(), CORS = emqx_conf:get([dashboard, cors], false), case CORS andalso cowboy_req:header(<<"origin">>, Req, undefined) of false -> @@ -31,3 +32,22 @@ execute(Req, Env) -> Req2 = cowboy_req:set_resp_header(<<"Access-Control-Allow-Origin">>, <<"*">>, Req), {ok, Req2, Env} end. + +waiting_dispatch_ready() -> + waiting_dispatch_ready(5). + +waiting_dispatch_ready(0) -> + ok; +waiting_dispatch_ready(Count) -> + case emqx_sys:uptime() < timer:minutes(1) of + true -> + case emqx_dashboard_listener:is_ready() of + true -> + ok; + false -> + timer:sleep(100), + waiting_dispatch_ready(Count - 1) + end; + false -> + ok + end.