diff options
author | j.uhlig <[email protected]> | 2018-04-09 12:53:02 +0200 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2018-05-02 17:21:11 +0200 |
commit | 7006c50c3ed6c3cbcb24e9e88a76ebd1aaf3a5f8 (patch) | |
tree | 4f34510579b6bff962e1906925b951504217f137 /src/ranch.erl | |
parent | e2d8d737677f464bd18a10b630417b770caa01cc (diff) | |
download | ranch-7006c50c3ed6c3cbcb24e9e88a76ebd1aaf3a5f8.tar.gz ranch-7006c50c3ed6c3cbcb24e9e88a76ebd1aaf3a5f8.tar.bz2 ranch-7006c50c3ed6c3cbcb24e9e88a76ebd1aaf3a5f8.zip |
Add suspend/resume of listeners and update of transport options
This allows graceful draining of connections, updating transport
options on a running listener without having to drop connections
and other similar scenarios.
Note that when updating transport options the listener must be
suspended which means that new connections will be rejected until
the listener is resumed.
Diffstat (limited to 'src/ranch.erl')
-rw-r--r-- | src/ranch.erl | 81 |
1 files changed, 77 insertions, 4 deletions
diff --git a/src/ranch.erl b/src/ranch.erl index 70fb64c..5af4b74 100644 --- a/src/ranch.erl +++ b/src/ranch.erl @@ -17,17 +17,23 @@ -export([start_listener/5]). -export([start_listener/6]). -export([stop_listener/1]). +-export([suspend_listener/1]). +-export([resume_listener/1]). -export([child_spec/5]). -export([child_spec/6]). -export([accept_ack/1]). -export([remove_connection/1]). +-export([get_status/1]). -export([get_addr/1]). -export([get_port/1]). -export([get_max_connections/1]). -export([set_max_connections/2]). +-export([get_transport_options/1]). +-export([set_transport_options/2]). -export([get_protocol_options/1]). -export([set_protocol_options/2]). -export([info/0]). +-export([info/1]). -export([procs/2]). -export([filter_options/3]). -export([set_option_default/3]). @@ -110,6 +116,37 @@ stop_listener(Ref) -> {error, Reason} end. +-spec suspend_listener(ref()) -> ok | {error, term()}. +suspend_listener(Ref) -> + case get_status(Ref) of + running -> + ListenerSup = ranch_server:get_listener_sup(Ref), + ok = ranch_server:set_addr(Ref, {undefined, undefined}), + supervisor:terminate_child(ListenerSup, ranch_acceptors_sup); + suspended -> + ok + end. + +-spec resume_listener(ref()) -> ok | {error, term()}. +resume_listener(Ref) -> + case get_status(Ref) of + running -> + ok; + suspended -> + ListenerSup = ranch_server:get_listener_sup(Ref), + Res = supervisor:restart_child(ListenerSup, ranch_acceptors_sup), + maybe_resumed(Res) + end. + +maybe_resumed(Error={error, {listen_error, _, Reason}}) -> + start_error(Reason, Error); +maybe_resumed({ok, _}) -> + ok; +maybe_resumed({ok, _, _}) -> + ok; +maybe_resumed(Res) -> + Res. + -spec child_spec(ref(), module(), any(), module(), any()) -> supervisor:child_spec(). child_spec(Ref, Transport, TransOpts, Protocol, ProtoOpts) -> @@ -137,11 +174,22 @@ remove_connection(Ref) -> ConnsSup ! {remove_connection, Ref, self()}, ok. --spec get_addr(ref()) -> {inet:ip_address(), inet:port_number()}. +-spec get_status(ref()) -> running | suspended | restarting. +get_status(Ref) -> + ListenerSup = ranch_server:get_listener_sup(Ref), + Children = supervisor:which_children(ListenerSup), + case lists:keyfind(ranch_acceptors_sup, 1, Children) of + {_, undefined, _, _} -> + suspended; + {_, AcceptorsSup, _, _} when is_pid(AcceptorsSup) -> + running + end. + +-spec get_addr(ref()) -> {inet:ip_address(), inet:port_number()} | {undefined, undefined}. get_addr(Ref) -> ranch_server:get_addr(Ref). --spec get_port(ref()) -> inet:port_number(). +-spec get_port(ref()) -> inet:port_number() | undefined. get_port(Ref) -> {_, Port} = get_addr(Ref), Port. @@ -154,6 +202,19 @@ get_max_connections(Ref) -> set_max_connections(Ref, MaxConnections) -> ranch_server:set_max_connections(Ref, MaxConnections). +-spec get_transport_options(ref()) -> any(). +get_transport_options(Ref) -> + ranch_server:get_transport_options(Ref). + +-spec set_transport_options(ref(), any()) -> ok | {error, running}. +set_transport_options(Ref, TransOpts) -> + case get_status(Ref) of + suspended -> + ok = ranch_server:set_transport_options(Ref, TransOpts); + running -> + {error, running} + end. + -spec get_protocol_options(ref()) -> any(). get_protocol_options(Ref) -> ranch_server:get_protocol_options(Ref). @@ -167,14 +228,22 @@ info() -> [{Ref, listener_info(Ref, Pid)} || {Ref, Pid} <- ranch_server:get_listener_sups()]. +-spec info(ref()) -> [{atom(), any()}]. +info(Ref) -> + Pid = ranch_server:get_listener_sup(Ref), + listener_info(Ref, Pid). + listener_info(Ref, Pid) -> - [_, NumAcceptors, Transport, TransOpts, Protocol, _] = ranch_server:get_listener_start_args(Ref), + [_, NumAcceptors, Transport, _, Protocol, _] = ranch_server:get_listener_start_args(Ref), ConnsSup = ranch_server:get_connections_sup(Ref), + Status = get_status(Ref), {IP, Port} = get_addr(Ref), MaxConns = get_max_connections(Ref), + TransOpts = ranch_server:get_transport_options(Ref), ProtoOpts = get_protocol_options(Ref), [ {pid, Pid}, + {status, Status}, {ip, IP}, {port, Port}, {num_acceptors, NumAcceptors}, @@ -197,7 +266,11 @@ procs1(Ref, Sup) -> ListenerSup = ranch_server:get_listener_sup(Ref), {_, SupPid, _, _} = lists:keyfind(Sup, 1, supervisor:which_children(ListenerSup)), - [Pid || {_, Pid, _, _} <- supervisor:which_children(SupPid)]. + try + [Pid || {_, Pid, _, _} <- supervisor:which_children(SupPid)] + catch exit:{noproc, _} when Sup =:= ranch_acceptors_sup -> + [] + end. -spec filter_options([inet | inet6 | {atom(), any()} | {raw, any(), any(), any()}], [atom()], Acc) -> Acc when Acc :: [any()]. |