Current section

Files

Jump to
nova src nova_app.erl
Raw

src/nova_app.erl

%%%-------------------------------------------------------------------
%% @doc
%% Nova application behaviour callback (Not used)
%% @end
%%%-------------------------------------------------------------------
-module(nova_app).
-behaviour(application).
-include_lib("kernel/include/logger.hrl").
%% Application callbacks
-export([start/2, prep_stop/1, stop/1]).
%%====================================================================
%% API
%%====================================================================
start(_StartType, _StartArgs) ->
nova_sup:start_link().
prep_stop(State) ->
graceful_shutdown(),
State.
stop(_State) ->
ok.
%%====================================================================
%% Internal functions
%%====================================================================
graceful_shutdown() ->
Delay = application:get_env(nova, shutdown_delay, 0),
case Delay > 0 of
true ->
?LOG_NOTICE(#{msg => <<"Graceful shutdown started">>, delay_ms => Delay}),
timer:sleep(Delay);
false ->
ok
end,
?LOG_NOTICE(#{msg => <<"Suspending listener">>}),
ranch:suspend_listener(nova_listener),
DrainTimeout = application:get_env(nova, shutdown_drain_timeout, 15000),
?LOG_NOTICE(#{msg => <<"Draining connections">>, timeout_ms => DrainTimeout}),
drain_connections(DrainTimeout),
?LOG_NOTICE(#{msg => <<"Stopping listener">>}),
cowboy:stop_listener(nova_listener),
ok.
drain_connections(Timeout) ->
Deadline = erlang:monotonic_time(millisecond) + Timeout,
drain_loop(Deadline).
drain_loop(Deadline) ->
case ranch:info(nova_listener) of
#{active_connections := 0} ->
ok;
#{active_connections := N} ->
Now = erlang:monotonic_time(millisecond),
case Now >= Deadline of
true ->
?LOG_WARNING(#{msg => <<"Drain timeout reached">>,
remaining_connections => N}),
ok;
false ->
timer:sleep(500),
drain_loop(Deadline)
end
end.