Improve the session module

This commit is contained in:
Feng Lee 2018-12-20 10:17:14 +08:00 committed by Feng Lee
parent 7a1ec580b0
commit 42fc8f5811
1 changed files with 88 additions and 82 deletions

View File

@ -158,8 +158,6 @@
-export_type([attr/0]). -export_type([attr/0]).
-define(TIMEOUT, 60000).
-define(LOG(Level, Format, Args, _State), -define(LOG(Level, Format, Args, _State),
emqx_logger:Level("[Session] " ++ Format, Args)). emqx_logger:Level("[Session] " ++ Format, Args)).
@ -261,9 +259,11 @@ subscribe(SPid, PacketId, Properties, TopicFilters) ->
publish(_SPid, _PacketId, Msg = #message{qos = ?QOS_0}) -> publish(_SPid, _PacketId, Msg = #message{qos = ?QOS_0}) ->
%% Publish QoS0 message directly %% Publish QoS0 message directly
emqx_broker:publish(Msg); emqx_broker:publish(Msg);
publish(_SPid, _PacketId, Msg = #message{qos = ?QOS_1}) -> publish(_SPid, _PacketId, Msg = #message{qos = ?QOS_1}) ->
%% Publish QoS1 message directly %% Publish QoS1 message directly
emqx_broker:publish(Msg); emqx_broker:publish(Msg);
publish(SPid, PacketId, Msg = #message{qos = ?QOS_2, timestamp = Ts}) -> publish(SPid, PacketId, Msg = #message{qos = ?QOS_2, timestamp = Ts}) ->
%% Register QoS2 message packet ID (and timestamp) to session, then publish %% Register QoS2 message packet ID (and timestamp) to session, then publish
case gen_server:call(SPid, {register_publish_packet_id, PacketId, Ts}, infinity) of case gen_server:call(SPid, {register_publish_packet_id, PacketId, Ts}, infinity) of
@ -275,6 +275,7 @@ publish(SPid, PacketId, Msg = #message{qos = ?QOS_2, timestamp = Ts}) ->
puback(SPid, PacketId) -> puback(SPid, PacketId) ->
gen_server:cast(SPid, {puback, PacketId, ?RC_SUCCESS}). gen_server:cast(SPid, {puback, PacketId, ?RC_SUCCESS}).
-spec(puback(spid(), emqx_mqtt_types:packet_id(), emqx_mqtt_types:reason_code()) -> ok).
puback(SPid, PacketId, ReasonCode) -> puback(SPid, PacketId, ReasonCode) ->
gen_server:cast(SPid, {puback, PacketId, ReasonCode}). gen_server:cast(SPid, {puback, PacketId, ReasonCode}).
@ -322,7 +323,7 @@ discard(SPid, ByPid) ->
-spec(update_expiry_interval(spid(), timeout()) -> ok). -spec(update_expiry_interval(spid(), timeout()) -> ok).
update_expiry_interval(SPid, Interval) -> update_expiry_interval(SPid, Interval) ->
gen_server:cast(SPid, {expiry_interval, Interval}). gen_server:cast(SPid, {update_expiry_interval, Interval}).
-spec(close(spid()) -> ok). -spec(close(spid()) -> ok).
close(SPid) -> close(SPid) ->
@ -340,9 +341,9 @@ init([Parent, #{zone := Zone,
expiry_interval := ExpiryInterval, expiry_interval := ExpiryInterval,
max_inflight := MaxInflight, max_inflight := MaxInflight,
will_msg := WillMsg}]) -> will_msg := WillMsg}]) ->
emqx_logger:set_metadata_client_id(ClientId),
process_flag(trap_exit, true), process_flag(trap_exit, true),
true = link(ConnPid), true = link(ConnPid),
emqx_logger:set_metadata_client_id(ClientId),
IdleTimout = get_env(Zone, idle_timeout, 30000), IdleTimout = get_env(Zone, idle_timeout, 30000),
State = #state{idle_timeout = IdleTimout, State = #state{idle_timeout = IdleTimout,
clean_start = CleanStart, clean_start = CleanStart,
@ -397,18 +398,19 @@ handle_call(stats, _From, State) ->
handle_call({discard, ByPid}, _From, State = #state{conn_pid = undefined}) -> handle_call({discard, ByPid}, _From, State = #state{conn_pid = undefined}) ->
?LOG(warning, "Discarded by ~p", [ByPid], State), ?LOG(warning, "Discarded by ~p", [ByPid], State),
{stop, {shutdown, discard}, ok, State}; {stop, discarded, ok, State};
handle_call({discard, ByPid}, _From, State = #state{client_id = ClientId, conn_pid = ConnPid}) -> handle_call({discard, ByPid}, _From, State = #state{client_id = ClientId, conn_pid = ConnPid}) ->
?LOG(warning, "Conn ~p is discarded by ~p", [ConnPid, ByPid], State), ?LOG(warning, "Conn ~p is discarded by ~p", [ConnPid, ByPid], State),
ConnPid ! {shutdown, discard, {ClientId, ByPid}}, ConnPid ! {shutdown, discard, {ClientId, ByPid}},
{stop, {shutdown, discard}, ok, State}; {stop, discarded, ok, State};
%% PUBLISH: This is only to register packetId to session state. %% PUBLISH: This is only to register packetId to session state.
%% The actual message dispatching should be done by the caller (e.g. connection) process. %% The actual message dispatching should be done by the caller (e.g. connection) process.
handle_call({register_publish_packet_id, PacketId, Ts}, _From, handle_call({register_publish_packet_id, PacketId, Ts}, _From,
State = #state{awaiting_rel = AwaitingRel}) -> State = #state{awaiting_rel = AwaitingRel}) ->
reply(case is_awaiting_full(State) of reply(
case is_awaiting_full(State) of
false -> false ->
case maps:is_key(PacketId, AwaitingRel) of case maps:is_key(PacketId, AwaitingRel) of
true -> true ->
@ -418,30 +420,32 @@ handle_call({register_publish_packet_id, PacketId, Ts}, _From,
{ok, ensure_await_rel_timer(State1)} {ok, ensure_await_rel_timer(State1)}
end; end;
true -> true ->
emqx_metrics:trans(inc, 'messages/qos2/dropped'),
?LOG(warning, "Dropped qos2 packet ~w for too many awaiting_rel", [PacketId], State), ?LOG(warning, "Dropped qos2 packet ~w for too many awaiting_rel", [PacketId], State),
emqx_metrics:trans(inc, 'messages/qos2/dropped'),
{{error, ?RC_RECEIVE_MAXIMUM_EXCEEDED}, State} {{error, ?RC_RECEIVE_MAXIMUM_EXCEEDED}, State}
end); end);
%% PUBREC: %% PUBREC:
handle_call({pubrec, PacketId, _ReasonCode}, _From, State = #state{inflight = Inflight}) -> handle_call({pubrec, PacketId, _ReasonCode}, _From, State = #state{inflight = Inflight}) ->
reply(case emqx_inflight:contain(PacketId, Inflight) of reply(
case emqx_inflight:contain(PacketId, Inflight) of
true -> true ->
{ok, acked(pubrec, PacketId, State)}; {ok, acked(pubrec, PacketId, State)};
false -> false ->
emqx_metrics:trans(inc, 'packets/pubrec/missed'),
?LOG(warning, "The PUBREC PacketId ~w is not found.", [PacketId], State), ?LOG(warning, "The PUBREC PacketId ~w is not found.", [PacketId], State),
emqx_metrics:trans(inc, 'packets/pubrec/missed'),
{{error, ?RC_PACKET_IDENTIFIER_NOT_FOUND}, State} {{error, ?RC_PACKET_IDENTIFIER_NOT_FOUND}, State}
end); end);
%% PUBREL: %% PUBREL:
handle_call({pubrel, PacketId, _ReasonCode}, _From, State = #state{awaiting_rel = AwaitingRel}) -> handle_call({pubrel, PacketId, _ReasonCode}, _From, State = #state{awaiting_rel = AwaitingRel}) ->
reply(case maps:take(PacketId, AwaitingRel) of reply(
case maps:take(PacketId, AwaitingRel) of
{_Ts, AwaitingRel1} -> {_Ts, AwaitingRel1} ->
{ok, State#state{awaiting_rel = AwaitingRel1}}; {ok, State#state{awaiting_rel = AwaitingRel1}};
error -> error ->
?LOG(warning, "The PUBREL PacketId ~w is not found", [PacketId], State),
emqx_metrics:trans(inc, 'packets/pubrel/missed'), emqx_metrics:trans(inc, 'packets/pubrel/missed'),
?LOG(warning, "Cannot find PUBREL: ~w", [PacketId], State),
{{error, ?RC_PACKET_IDENTIFIER_NOT_FOUND}, State} {{error, ?RC_PACKET_IDENTIFIER_NOT_FOUND}, State}
end); end);
@ -494,25 +498,27 @@ handle_cast({unsubscribe, From, {PacketId, _Properties, TopicFilters}},
%% PUBACK: %% PUBACK:
handle_cast({puback, PacketId, _ReasonCode}, State = #state{inflight = Inflight}) -> handle_cast({puback, PacketId, _ReasonCode}, State = #state{inflight = Inflight}) ->
noreply(
case emqx_inflight:contain(PacketId, Inflight) of case emqx_inflight:contain(PacketId, Inflight) of
true -> true ->
noreply(dequeue(acked(puback, PacketId, State))); dequeue(acked(puback, PacketId, State));
false -> false ->
?LOG(warning, "The PUBACK PacketId ~w is not found", [PacketId], State), ?LOG(warning, "The PUBACK PacketId ~w is not found", [PacketId], State),
emqx_metrics:trans(inc, 'packets/puback/missed'), emqx_metrics:trans(inc, 'packets/puback/missed'),
{noreply, State} State
end; end);
%% PUBCOMP: %% PUBCOMP:
handle_cast({pubcomp, PacketId, _ReasonCode}, State = #state{inflight = Inflight}) -> handle_cast({pubcomp, PacketId, _ReasonCode}, State = #state{inflight = Inflight}) ->
noreply(
case emqx_inflight:contain(PacketId, Inflight) of case emqx_inflight:contain(PacketId, Inflight) of
true -> true ->
noreply(dequeue(acked(pubcomp, PacketId, State))); dequeue(acked(pubcomp, PacketId, State));
false -> false ->
?LOG(warning, "The PUBCOMP PacketId ~w is not found", [PacketId], State), ?LOG(warning, "The PUBCOMP PacketId ~w is not found", [PacketId], State),
emqx_metrics:trans(inc, 'packets/pubcomp/missed'), emqx_metrics:trans(inc, 'packets/pubcomp/missed'),
{noreply, State} State
end; end);
%% RESUME: %% RESUME:
handle_cast({resume, #{conn_pid := ConnPid, handle_cast({resume, #{conn_pid := ConnPid,
@ -561,7 +567,7 @@ handle_cast({resume, #{conn_pid := ConnPid,
%% Replay delivery and Dequeue pending messages %% Replay delivery and Dequeue pending messages
noreply(dequeue(retry_delivery(true, State1))); noreply(dequeue(retry_delivery(true, State1)));
handle_cast({expiry_interval, Interval}, State) -> handle_cast({update_expiry_interval, Interval}, State) ->
{noreply, State#state{expiry_interval = Interval}}; {noreply, State#state{expiry_interval = Interval}};
handle_cast(Msg, State) -> handle_cast(Msg, State) ->