feat: reserved 1-1024 topic id for predefined topics
This commit is contained in:
parent
ac6693c8cc
commit
9c4a576fb3
|
@ -14,6 +14,8 @@
|
||||||
%% limitations under the License.
|
%% limitations under the License.
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
-define(SN_MAX_PREDEF_TOPIC_ID, 1024).
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% MQTT-SN Types
|
%% MQTT-SN Types
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
|
@ -33,38 +33,40 @@
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-define(PKEY(Id), {mqttsn, predef_topics, Id}).
|
-define(PKEY(Id), {mqttsn, predef_topics, Id}).
|
||||||
-define(PKEY_MAX_PREDEF_ID, {mqttsn, max_predef_topic_id}).
|
|
||||||
|
|
||||||
-type registry() :: #{
|
-type registry() :: #{
|
||||||
%% The next topic id to be assigned to new registration
|
%% The next topic id to be assigned to new registration
|
||||||
next_topic_id := pos_integer(),
|
last_topic_id := pos_integer(),
|
||||||
%% The mapping from topic id to topic name
|
%% The mapping from topic id to topic name
|
||||||
id_to_name := map(),
|
id_to_name := map(),
|
||||||
%% The mapping from topic name to topic id
|
%% The mapping from topic name to topic id
|
||||||
name_to_id := map()
|
name_to_id := map()
|
||||||
}.
|
}.
|
||||||
|
|
||||||
%%-----------------------------------------------------------------------------
|
-type predef_topic() :: #{
|
||||||
|
id := 1..1024,
|
||||||
|
topic := iolist()
|
||||||
|
}.
|
||||||
|
|
||||||
-spec persist_predefined_topics(list()) -> ok.
|
%%-----------------------------------------------------------------------------
|
||||||
|
%% APIs
|
||||||
|
|
||||||
|
-spec persist_predefined_topics([predef_topic()]) -> ok.
|
||||||
persist_predefined_topics(PredefTopics) when is_list(PredefTopics) ->
|
persist_predefined_topics(PredefTopics) when is_list(PredefTopics) ->
|
||||||
MaxPredefId = lists:foldl(
|
try
|
||||||
fun(#{id := TopicId, topic := TopicName0}, AccId) ->
|
F = fun(#{id := TopicId, topic := TopicName0}) when TopicId =< 1024 ->
|
||||||
TopicName = iolist_to_binary(TopicName0),
|
TopicName = iolist_to_binary(TopicName0),
|
||||||
persistent_term:put(?PKEY(TopicId), TopicName),
|
persistent_term:put(?PKEY(TopicId), TopicName),
|
||||||
persistent_term:put(?PKEY(TopicName), TopicId),
|
persistent_term:put(?PKEY(TopicName), TopicId)
|
||||||
case TopicId > AccId of
|
|
||||||
true -> TopicId;
|
|
||||||
false -> AccId
|
|
||||||
end
|
|
||||||
end,
|
end,
|
||||||
0,
|
lists:foreach(F, PredefTopics)
|
||||||
PredefTopics
|
catch
|
||||||
),
|
_:_ ->
|
||||||
persistent_term:put(?PKEY_MAX_PREDEF_ID, MaxPredefId),
|
clear_predefined_topics(PredefTopics),
|
||||||
ok.
|
error(badarg)
|
||||||
|
end.
|
||||||
|
|
||||||
-spec clear_predefined_topics(list()) -> ok.
|
-spec clear_predefined_topics([predef_topic()]) -> ok.
|
||||||
clear_predefined_topics(PredefTopics) ->
|
clear_predefined_topics(PredefTopics) ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(#{id := TopicId, topic := TopicName0}) ->
|
fun(#{id := TopicId, topic := TopicName0}) ->
|
||||||
|
@ -74,13 +76,12 @@ clear_predefined_topics(PredefTopics) ->
|
||||||
end,
|
end,
|
||||||
PredefTopics
|
PredefTopics
|
||||||
),
|
),
|
||||||
persistent_term:erase(?PKEY_MAX_PREDEF_ID),
|
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-spec init() -> registry().
|
-spec init() -> registry().
|
||||||
init() ->
|
init() ->
|
||||||
#{
|
#{
|
||||||
next_topic_id => persistent_term:get(?PKEY_MAX_PREDEF_ID, 0),
|
last_topic_id => ?SN_MAX_PREDEF_TOPIC_ID,
|
||||||
id_to_name => #{},
|
id_to_name => #{},
|
||||||
name_to_id => #{}
|
name_to_id => #{}
|
||||||
}.
|
}.
|
||||||
|
@ -113,7 +114,7 @@ reg(
|
||||||
do_reg(
|
do_reg(
|
||||||
TopicName,
|
TopicName,
|
||||||
Registry = #{
|
Registry = #{
|
||||||
next_topic_id := TopicId0,
|
last_topic_id := TopicId0,
|
||||||
id_to_name := IdMap,
|
id_to_name := IdMap,
|
||||||
name_to_id := NameMap
|
name_to_id := NameMap
|
||||||
}
|
}
|
||||||
|
@ -123,7 +124,7 @@ do_reg(
|
||||||
{error, too_large};
|
{error, too_large};
|
||||||
NextTopicId ->
|
NextTopicId ->
|
||||||
NRegistry = Registry#{
|
NRegistry = Registry#{
|
||||||
next_topic_id := NextTopicId,
|
last_topic_id := NextTopicId,
|
||||||
id_to_name := maps:put(NextTopicId, TopicName, IdMap),
|
id_to_name := maps:put(NextTopicId, TopicName, IdMap),
|
||||||
name_to_id := maps:put(TopicName, NextTopicId, NameMap)
|
name_to_id := maps:put(TopicName, NextTopicId, NameMap)
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
-module(emqx_mqttsn_schema).
|
-module(emqx_mqttsn_schema).
|
||||||
|
|
||||||
|
-include("emqx_mqttsn.hrl").
|
||||||
-include_lib("hocon/include/hoconsc.hrl").
|
-include_lib("hocon/include/hoconsc.hrl").
|
||||||
-include_lib("typerefl/include/types.hrl").
|
-include_lib("typerefl/include/types.hrl").
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ fields(mqttsn) ->
|
||||||
fields(mqttsn_predefined) ->
|
fields(mqttsn_predefined) ->
|
||||||
[
|
[
|
||||||
{id,
|
{id,
|
||||||
sc(integer(), #{
|
sc(range(1, ?SN_MAX_PREDEF_TOPIC_ID), #{
|
||||||
required => true,
|
required => true,
|
||||||
desc => ?DESC(mqttsn_predefined_id)
|
desc => ?DESC(mqttsn_predefined_id)
|
||||||
})},
|
})},
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
|
|
||||||
-define(LOG(Format, Args), ct:log("TEST: " ++ Format, Args)).
|
-define(LOG(Format, Args), ct:log("TEST: " ++ Format, Args)).
|
||||||
|
|
||||||
-define(MAX_PRED_TOPIC_ID, 2).
|
-define(MAX_PRED_TOPIC_ID, ?SN_MAX_PREDEF_TOPIC_ID).
|
||||||
-define(PREDEF_TOPIC_ID1, 1).
|
-define(PREDEF_TOPIC_ID1, 1).
|
||||||
-define(PREDEF_TOPIC_ID2, 2).
|
-define(PREDEF_TOPIC_ID2, 2).
|
||||||
-define(PREDEF_TOPIC_NAME1, <<"/predefined/topic/name/hello">>).
|
-define(PREDEF_TOPIC_NAME1, <<"/predefined/topic/name/hello">>).
|
||||||
|
|
|
@ -19,10 +19,11 @@
|
||||||
-compile(export_all).
|
-compile(export_all).
|
||||||
-compile(nowarn_export_all).
|
-compile(nowarn_export_all).
|
||||||
|
|
||||||
|
-include("emqx_mqttsn.hrl").
|
||||||
-include_lib("eunit/include/eunit.hrl").
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
||||||
-define(REGISTRY, emqx_mqttsn_registry).
|
-define(REGISTRY, emqx_mqttsn_registry).
|
||||||
-define(MAX_PREDEF_ID, 2).
|
-define(MAX_PREDEF_ID, ?SN_MAX_PREDEF_TOPIC_ID).
|
||||||
-define(PREDEF_TOPICS, [
|
-define(PREDEF_TOPICS, [
|
||||||
#{id => 1, topic => <<"/predefined/topic/name/hello">>},
|
#{id => 1, topic => <<"/predefined/topic/name/hello">>},
|
||||||
#{id => 2, topic => <<"/predefined/topic/name/nice">>}
|
#{id => 2, topic => <<"/predefined/topic/name/nice">>}
|
||||||
|
@ -75,8 +76,8 @@ t_reach_maximum(_) ->
|
||||||
Reg0 = ?REGISTRY:init(),
|
Reg0 = ?REGISTRY:init(),
|
||||||
Reg = register_a_lot(?MAX_PREDEF_ID + 1, 16#ffff, Reg0),
|
Reg = register_a_lot(?MAX_PREDEF_ID + 1, 16#ffff, Reg0),
|
||||||
?assertEqual({error, too_large}, ?REGISTRY:reg(<<"TopicABC">>, Reg)),
|
?assertEqual({error, too_large}, ?REGISTRY:reg(<<"TopicABC">>, Reg)),
|
||||||
?assertEqual(?MAX_PREDEF_ID + 1, ?REGISTRY:lookup_topic_id(<<"Topic3">>, Reg)),
|
?assertEqual(?MAX_PREDEF_ID + 1, ?REGISTRY:lookup_topic_id(<<"Topic1025">>, Reg)),
|
||||||
?assertEqual(?MAX_PREDEF_ID + 2, ?REGISTRY:lookup_topic_id(<<"Topic4">>, Reg)).
|
?assertEqual(?MAX_PREDEF_ID + 2, ?REGISTRY:lookup_topic_id(<<"Topic1026">>, Reg)).
|
||||||
|
|
||||||
t_deny_wildcard_topic(_) ->
|
t_deny_wildcard_topic(_) ->
|
||||||
Reg = ?REGISTRY:init(),
|
Reg = ?REGISTRY:init(),
|
||||||
|
|
Loading…
Reference in New Issue