fix(sessds): Apply review remarks
This commit is contained in:
parent
39857626ce
commit
f5b9bd30aa
|
@ -373,7 +373,7 @@ publish(_PacketId, Msg, Session) ->
|
||||||
{ok, emqx_types:message(), replies(), session()}
|
{ok, emqx_types:message(), replies(), session()}
|
||||||
| {error, emqx_types:reason_code()}.
|
| {error, emqx_types:reason_code()}.
|
||||||
puback(_ClientInfo, PacketId, Session0) ->
|
puback(_ClientInfo, PacketId, Session0) ->
|
||||||
case commit_seqno(puback, PacketId, Session0) of
|
case update_seqno(puback, PacketId, Session0) of
|
||||||
{ok, Msg, Session} ->
|
{ok, Msg, Session} ->
|
||||||
{ok, Msg, [], inc_send_quota(Session)};
|
{ok, Msg, [], inc_send_quota(Session)};
|
||||||
Error ->
|
Error ->
|
||||||
|
@ -388,7 +388,7 @@ puback(_ClientInfo, PacketId, Session0) ->
|
||||||
{ok, emqx_types:message(), session()}
|
{ok, emqx_types:message(), session()}
|
||||||
| {error, emqx_types:reason_code()}.
|
| {error, emqx_types:reason_code()}.
|
||||||
pubrec(PacketId, Session0) ->
|
pubrec(PacketId, Session0) ->
|
||||||
case commit_seqno(pubrec, PacketId, Session0) of
|
case update_seqno(pubrec, PacketId, Session0) of
|
||||||
{ok, Msg, Session} ->
|
{ok, Msg, Session} ->
|
||||||
{ok, Msg, Session};
|
{ok, Msg, Session};
|
||||||
Error = {error, _} ->
|
Error = {error, _} ->
|
||||||
|
@ -413,7 +413,7 @@ pubrel(_PacketId, Session = #{}) ->
|
||||||
{ok, emqx_types:message(), replies(), session()}
|
{ok, emqx_types:message(), replies(), session()}
|
||||||
| {error, emqx_types:reason_code()}.
|
| {error, emqx_types:reason_code()}.
|
||||||
pubcomp(_ClientInfo, PacketId, Session0) ->
|
pubcomp(_ClientInfo, PacketId, Session0) ->
|
||||||
case commit_seqno(pubcomp, PacketId, Session0) of
|
case update_seqno(pubcomp, PacketId, Session0) of
|
||||||
{ok, Msg, Session} ->
|
{ok, Msg, Session} ->
|
||||||
{ok, Msg, [], inc_send_quota(Session)};
|
{ok, Msg, [], inc_send_quota(Session)};
|
||||||
Error = {error, _} ->
|
Error = {error, _} ->
|
||||||
|
@ -540,6 +540,7 @@ sync(ClientId) ->
|
||||||
{'DOWN', Ref, process, _Pid, Reason} ->
|
{'DOWN', Ref, process, _Pid, Reason} ->
|
||||||
{error, Reason};
|
{error, Reason};
|
||||||
Ref ->
|
Ref ->
|
||||||
|
demonitor(Ref, [flush]),
|
||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
[] ->
|
[] ->
|
||||||
|
@ -767,7 +768,7 @@ process_batch(
|
||||||
SeqNoQos2 = inc_seqno(?QOS_2, SeqNoQos20)
|
SeqNoQos2 = inc_seqno(?QOS_2, SeqNoQos20)
|
||||||
end,
|
end,
|
||||||
{
|
{
|
||||||
case Msg#message.qos of
|
case Qos of
|
||||||
?QOS_0 when IsReplay ->
|
?QOS_0 when IsReplay ->
|
||||||
%% We ignore QoS 0 messages during replay:
|
%% We ignore QoS 0 messages during replay:
|
||||||
Acc;
|
Acc;
|
||||||
|
@ -895,9 +896,9 @@ bump_interval() ->
|
||||||
%% SeqNo tracking
|
%% SeqNo tracking
|
||||||
%% --------------------------------------------------------------------
|
%% --------------------------------------------------------------------
|
||||||
|
|
||||||
-spec commit_seqno(puback | pubrec | pubcomp, emqx_types:packet_id(), session()) ->
|
-spec update_seqno(puback | pubrec | pubcomp, emqx_types:packet_id(), session()) ->
|
||||||
{ok, emqx_types:message(), session()} | {error, _}.
|
{ok, emqx_types:message(), session()} | {error, _}.
|
||||||
commit_seqno(Track, PacketId, Session = #{id := SessionId, s := S}) ->
|
update_seqno(Track, PacketId, Session = #{id := SessionId, s := S}) ->
|
||||||
SeqNo = packet_id_to_seqno(PacketId, S),
|
SeqNo = packet_id_to_seqno(PacketId, S),
|
||||||
case Track of
|
case Track of
|
||||||
puback ->
|
puback ->
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
%% -----|----------|-----|-----|------> seqno
|
%% -----|----------|-----|-----|------> seqno
|
||||||
%% | | | |
|
%% | | | |
|
||||||
%% committed dup rec next
|
%% committed dup rec next
|
||||||
% (Qos2)
|
%% (Qos2)
|
||||||
|
|
||||||
%% Seqno becomes committed after receiving PUBACK for QoS1 or PUBCOMP
|
%% Seqno becomes committed after receiving PUBACK for QoS1 or PUBCOMP
|
||||||
%% for QoS2.
|
%% for QoS2.
|
||||||
|
@ -41,23 +41,26 @@
|
||||||
%% committed..dup range are retransmitted with DUP flag.
|
%% committed..dup range are retransmitted with DUP flag.
|
||||||
%%
|
%%
|
||||||
-define(dup(QOS), (10 + QOS)).
|
-define(dup(QOS), (10 + QOS)).
|
||||||
|
%% Rec flag is specific for the QoS2. It contains seqno of the last
|
||||||
|
%% PUBREC received from the client. When the session reconnects,
|
||||||
|
%% PUBREL packages for the dup..rec range are retransmitted.
|
||||||
-define(rec, 22).
|
-define(rec, 22).
|
||||||
%% Last seqno assigned to a message.
|
%% Last seqno assigned to a message (it may not be sent yet).
|
||||||
-define(next(QOS), (30 + QOS)).
|
-define(next(QOS), (30 + QOS)).
|
||||||
|
|
||||||
%%%%% State of the stream:
|
%%%%% State of the stream:
|
||||||
-record(ifs, {
|
-record(ifs, {
|
||||||
rank_x :: emqx_ds:rank_x(),
|
rank_x :: emqx_ds:rank_x(),
|
||||||
rank_y :: emqx_ds:rank_y(),
|
rank_y :: emqx_ds:rank_y(),
|
||||||
%% Iterator at the beginning and end of the last batch:
|
%% Iterators at the beginning and the end of the last batch:
|
||||||
it_begin :: emqx_ds:iterator() | undefined,
|
it_begin :: emqx_ds:iterator() | undefined,
|
||||||
it_end :: emqx_ds:iterator() | end_of_stream,
|
it_end :: emqx_ds:iterator() | end_of_stream,
|
||||||
%% Key that points at the beginning of the batch:
|
%% Size of the last batch:
|
||||||
batch_size = 0 :: non_neg_integer(),
|
batch_size = 0 :: non_neg_integer(),
|
||||||
%% Session sequence number at the time when the batch was fetched:
|
%% Session sequence numbers at the time when the batch was fetched:
|
||||||
first_seqno_qos1 = 0 :: emqx_persistent_session_ds:seqno(),
|
first_seqno_qos1 = 0 :: emqx_persistent_session_ds:seqno(),
|
||||||
first_seqno_qos2 = 0 :: emqx_persistent_session_ds:seqno(),
|
first_seqno_qos2 = 0 :: emqx_persistent_session_ds:seqno(),
|
||||||
%% Number of messages collected in the last batch:
|
%% Sequence numbers that have to be committed for the batch:
|
||||||
last_seqno_qos1 = 0 :: emqx_persistent_session_ds:seqno(),
|
last_seqno_qos1 = 0 :: emqx_persistent_session_ds:seqno(),
|
||||||
last_seqno_qos2 = 0 :: emqx_persistent_session_ds:seqno()
|
last_seqno_qos2 = 0 :: emqx_persistent_session_ds:seqno()
|
||||||
}).
|
}).
|
||||||
|
|
|
@ -126,7 +126,7 @@ gc_loop(MinLastAlive, It0) ->
|
||||||
|
|
||||||
do_gc(SessionId, MinLastAlive, LastAliveAt, EI) when LastAliveAt + EI < MinLastAlive ->
|
do_gc(SessionId, MinLastAlive, LastAliveAt, EI) when LastAliveAt + EI < MinLastAlive ->
|
||||||
emqx_persistent_session_ds:destroy_session(SessionId),
|
emqx_persistent_session_ds:destroy_session(SessionId),
|
||||||
?tp(error, ds_session_gc_cleaned, #{
|
?tp(debug, ds_session_gc_cleaned, #{
|
||||||
session_id => SessionId,
|
session_id => SessionId,
|
||||||
last_alive_at => LastAliveAt,
|
last_alive_at => LastAliveAt,
|
||||||
expiry_interval => EI,
|
expiry_interval => EI,
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
%% API:
|
%% API:
|
||||||
-export([new/1, push/2, pop/1, n_buffered/2, n_inflight/1, inc_send_quota/1, receive_maximum/1]).
|
-export([new/1, push/2, pop/1, n_buffered/2, n_inflight/1, inc_send_quota/1, receive_maximum/1]).
|
||||||
|
|
||||||
%% behavior callbacks:
|
|
||||||
-export([]).
|
|
||||||
|
|
||||||
%% internal exports:
|
%% internal exports:
|
||||||
-export([]).
|
-export([]).
|
||||||
|
|
||||||
|
|
|
@ -68,9 +68,10 @@
|
||||||
%% It should be possible to make frequent changes to the pmap without
|
%% It should be possible to make frequent changes to the pmap without
|
||||||
%% stressing Mria.
|
%% stressing Mria.
|
||||||
%%
|
%%
|
||||||
%% It's implemented as three maps: `clean', `dirty' and `tombstones'.
|
%% It's implemented as two maps: `cache', and `dirty'. `cache' stores
|
||||||
%% Updates are made to the `dirty' area. `pmap_commit' function saves
|
%% the data, and `dirty' contains information about dirty and deleted
|
||||||
%% the updated entries to Mnesia and moves them to the `clean' area.
|
%% keys. When `commit/1' is called, dirty keys are dumped to the
|
||||||
|
%% tables, and deleted keys are removed from the tables.
|
||||||
-record(pmap, {table, cache, dirty}).
|
-record(pmap, {table, cache, dirty}).
|
||||||
|
|
||||||
-type pmap(K, V) ::
|
-type pmap(K, V) ::
|
||||||
|
@ -530,9 +531,9 @@ kv_pmap_persist(Tab, SessionId, Key, Val0) ->
|
||||||
mnesia:write(Tab, #kv{k = {SessionId, Key}, v = Val}, write).
|
mnesia:write(Tab, #kv{k = {SessionId, Key}, v = Val}, write).
|
||||||
|
|
||||||
kv_pmap_restore(Table, SessionId) ->
|
kv_pmap_restore(Table, SessionId) ->
|
||||||
MS = [{#kv{k = {SessionId, '_'}, _ = '_'}, [], ['$_']}],
|
MS = [{#kv{k = {SessionId, '$1'}, v = '$2'}, [], [{{'$1', '$2'}}]}],
|
||||||
Objs = mnesia:select(Table, MS, read),
|
Objs = mnesia:select(Table, MS, read),
|
||||||
[{K, encoder(decode, Table, V)} || #kv{k = {_, K}, v = V} <- Objs].
|
[{K, encoder(decode, Table, V)} || {K, V} <- Objs].
|
||||||
|
|
||||||
kv_pmap_delete(Table, SessionId) ->
|
kv_pmap_delete(Table, SessionId) ->
|
||||||
MS = [{#kv{k = {SessionId, '$1'}, _ = '_'}, [], ['$1']}],
|
MS = [{#kv{k = {SessionId, '$1'}, _ = '_'}, [], ['$1']}],
|
||||||
|
|
|
@ -142,7 +142,7 @@ ensure_iterator(TopicFilter, StartTime, SubId, {{RankX, RankY}, Stream}, S) ->
|
||||||
case emqx_persistent_session_ds_state:get_stream(Key, S) of
|
case emqx_persistent_session_ds_state:get_stream(Key, S) of
|
||||||
undefined ->
|
undefined ->
|
||||||
?SLOG(debug, #{
|
?SLOG(debug, #{
|
||||||
'$msg' => new_stream, key => Key, stream => Stream
|
msg => new_stream, key => Key, stream => Stream
|
||||||
}),
|
}),
|
||||||
{ok, Iterator} = emqx_ds:make_iterator(
|
{ok, Iterator} = emqx_ds:make_iterator(
|
||||||
?PERSISTENT_MESSAGE_DB, Stream, TopicFilter, StartTime
|
?PERSISTENT_MESSAGE_DB, Stream, TopicFilter, StartTime
|
||||||
|
|
|
@ -554,7 +554,7 @@ t_process_dies_session_expires(Config) ->
|
||||||
|
|
||||||
ok = publish(Topic, Payload),
|
ok = publish(Topic, Payload),
|
||||||
|
|
||||||
timer:sleep(1100),
|
timer:sleep(2000),
|
||||||
|
|
||||||
{ok, Client2} = emqtt:start_link([
|
{ok, Client2} = emqtt:start_link([
|
||||||
{proto_ver, v5},
|
{proto_ver, v5},
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
Optimize performance of the RocksDB-based persistent session.
|
||||||
|
Reduce RAM usage and frequency of database requests.
|
||||||
|
|
||||||
|
- Introduce dirty session state to avoid frequent mria transactions
|
||||||
|
- Introduce an intermediate buffer for the persistent messages
|
||||||
|
- Use separate tracks of PacketIds for QoS1 and QoS2 messages
|
||||||
|
- Limit the number of continuous ranges of infligtht messages to one per stream
|
Loading…
Reference in New Issue