improve keepalie
This commit is contained in:
parent
273149f633
commit
78288e8088
|
@ -23,62 +23,61 @@
|
|||
%%%
|
||||
%%% @end
|
||||
%%%-----------------------------------------------------------------------------
|
||||
|
||||
-module(emqttd_keepalive).
|
||||
|
||||
-author("Feng Lee <feng@emqtt.io>").
|
||||
|
||||
-export([new/3, resume/1, cancel/1]).
|
||||
-export([start/3, check/1, cancel/1]).
|
||||
|
||||
-record(keepalive, {transport,
|
||||
socket,
|
||||
recv_oct,
|
||||
timeout_sec,
|
||||
timeout_msg,
|
||||
timer_ref}).
|
||||
-record(keepalive, {statfun, statval,
|
||||
tsec, tmsg, tref,
|
||||
repeat = 0}).
|
||||
|
||||
%%------------------------------------------------------------------------------
|
||||
%% @doc Create a keepalive
|
||||
%% @doc Start a keepalive
|
||||
%% @end
|
||||
%%------------------------------------------------------------------------------
|
||||
new({Transport, Socket}, TimeoutSec, TimeoutMsg) when TimeoutSec > 0 ->
|
||||
{ok, [{recv_oct, RecvOct}]} = Transport:getstat(Socket, [recv_oct]),
|
||||
Ref = erlang:send_after(timer:seconds(TimeoutSec), self(), TimeoutMsg),
|
||||
#keepalive {transport = Transport,
|
||||
socket = Socket,
|
||||
recv_oct = RecvOct,
|
||||
timeout_sec = TimeoutSec,
|
||||
timeout_msg = TimeoutMsg,
|
||||
timer_ref = Ref}.
|
||||
start(_, 0, _) ->
|
||||
undefined;
|
||||
start(StatFun, TimeoutSec, TimeoutMsg) ->
|
||||
{ok, StatVal} = StatFun(),
|
||||
#keepalive{statfun = StatFun, statval = StatVal,
|
||||
tsec = TimeoutSec, tmsg = TimeoutMsg,
|
||||
tref = timer(TimeoutSec, TimeoutMsg)}.
|
||||
|
||||
%%------------------------------------------------------------------------------
|
||||
%% @doc Try to resume keepalive, called when timeout
|
||||
%% @doc Check keepalive, called when timeout.
|
||||
%% @end
|
||||
%%------------------------------------------------------------------------------
|
||||
resume(KeepAlive = #keepalive {transport = Transport,
|
||||
socket = Socket,
|
||||
recv_oct = RecvOct,
|
||||
timeout_sec = TimeoutSec,
|
||||
timeout_msg = TimeoutMsg,
|
||||
timer_ref = Ref }) ->
|
||||
{ok, [{recv_oct, NewRecvOct}]} = Transport:getstat(Socket, [recv_oct]),
|
||||
if
|
||||
NewRecvOct =:= RecvOct ->
|
||||
timeout;
|
||||
check(KeepAlive = #keepalive{statfun = StatFun, statval = LastVal, repeat = Repeat}) ->
|
||||
case StatFun() of
|
||||
{ok, NewVal} ->
|
||||
if NewVal =/= LastVal ->
|
||||
{ok, resume(KeepAlive#keepalive{statval = NewVal, repeat = 0})};
|
||||
Repeat < 1 ->
|
||||
{ok, resume(KeepAlive#keepalive{statval = NewVal, repeat = Repeat + 1})};
|
||||
true ->
|
||||
%need?
|
||||
cancel(Ref),
|
||||
NewRef = erlang:send_after(timer:seconds(TimeoutSec), self(), TimeoutMsg),
|
||||
{resumed, KeepAlive#keepalive{recv_oct = NewRecvOct, timer_ref = NewRef}}
|
||||
{error, timeout}
|
||||
end;
|
||||
{error, Error} ->
|
||||
{error, Error}
|
||||
end.
|
||||
|
||||
resume(KeepAlive = #keepalive{tsec = TimeoutSec, tmsg = TimeoutMsg}) ->
|
||||
KeepAlive#keepalive{tref = timer(TimeoutSec, TimeoutMsg)}.
|
||||
|
||||
%%------------------------------------------------------------------------------
|
||||
%% @doc Cancel Keepalive
|
||||
%% @end
|
||||
%%------------------------------------------------------------------------------
|
||||
cancel(#keepalive{timer_ref = Ref}) ->
|
||||
cancel(Ref);
|
||||
cancel(#keepalive{tref = TRef}) ->
|
||||
cancel(TRef);
|
||||
cancel(undefined) ->
|
||||
undefined;
|
||||
cancel(Ref) ->
|
||||
catch erlang:cancel_timer(Ref).
|
||||
ok;
|
||||
cancel(TRef) ->
|
||||
catch erlang:cancel_timer(TRef).
|
||||
|
||||
timer(Sec, Msg) ->
|
||||
erlang:send_after(timer:seconds(Sec), self(), Msg).
|
||||
|
||||
|
|
Loading…
Reference in New Issue