Add emqx_portal:ensure_foreard_present API
This commit is contained in:
parent
9e78c18681
commit
2903a810ce
9
Makefile
9
Makefile
|
@ -101,12 +101,19 @@ rebar-eunit: $(CUTTLEFISH_SCRIPT)
|
||||||
rebar-compile:
|
rebar-compile:
|
||||||
@rebar3 compile
|
@rebar3 compile
|
||||||
|
|
||||||
rebar-ct: app.config
|
rebar-ct-setup: app.config
|
||||||
@rebar3 as test compile
|
@rebar3 as test compile
|
||||||
@ln -s -f '../../../../etc' _build/test/lib/emqx/
|
@ln -s -f '../../../../etc' _build/test/lib/emqx/
|
||||||
@ln -s -f '../../../../data' _build/test/lib/emqx/
|
@ln -s -f '../../../../data' _build/test/lib/emqx/
|
||||||
|
|
||||||
|
rebar-ct: rebar-ct-setup
|
||||||
@rebar3 ct -v --readable=false --name $(CT_NODE_NAME) --suite=$(shell echo $(foreach var,$(CT_SUITES),test/$(var)_SUITE) | tr ' ' ',')
|
@rebar3 ct -v --readable=false --name $(CT_NODE_NAME) --suite=$(shell echo $(foreach var,$(CT_SUITES),test/$(var)_SUITE) | tr ' ' ',')
|
||||||
|
|
||||||
|
## Run one single CT with rebar3
|
||||||
|
## e.g. make ct-one-suite suite=emqx_portal
|
||||||
|
ct-one-suite: rebar-ct-setup
|
||||||
|
@rebar3 ct -v --readable=false --name $(CT_NODE_NAME) --suite=$(suite)_SUITE
|
||||||
|
|
||||||
rebar-clean:
|
rebar-clean:
|
||||||
@rebar3 clean
|
@rebar3 clean
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@
|
||||||
-export([connecting/3, connected/3]).
|
-export([connecting/3, connected/3]).
|
||||||
|
|
||||||
%% management APIs
|
%% management APIs
|
||||||
-export([get_forwards/1]). %, add_forward/2, del_forward/2]).
|
-export([get_forwards/1, ensure_forward_present/2]). %, del_forward/2]).
|
||||||
-export([get_subscriptions/1]). %, add_subscription/3, del_subscription/2]).
|
-export([get_subscriptions/1]). %, add_subscription/3, del_subscription/2]).
|
||||||
|
|
||||||
-export_type([config/0,
|
-export_type([config/0,
|
||||||
|
@ -86,6 +86,7 @@
|
||||||
-type config() :: map().
|
-type config() :: map().
|
||||||
-type batch() :: [emqx_portal_msg:exp_msg()].
|
-type batch() :: [emqx_portal_msg:exp_msg()].
|
||||||
-type ack_ref() :: term().
|
-type ack_ref() :: term().
|
||||||
|
-type topic() :: emqx_topic:topic().
|
||||||
|
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
-include("emqx_mqtt.hrl").
|
-include("emqx_mqtt.hrl").
|
||||||
|
@ -137,8 +138,13 @@ handle_ack(Pid, Ref) when node() =:= node(Pid) ->
|
||||||
Pid ! {batch_ack, Ref},
|
Pid ! {batch_ack, Ref},
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-spec get_forwards(id()) -> [emqx_topic:topic()].
|
%% @doc Return all forwards (local subscriptions).
|
||||||
get_forwards(Id) -> gen_statem:call(id(Id), get_forwards).
|
-spec get_forwards(id()) -> [topic()].
|
||||||
|
get_forwards(Id) -> gen_statem:call(id(Id), get_forwards, timer:seconds(1000)).
|
||||||
|
|
||||||
|
%% @doc Add a new forward (local topic subscription).
|
||||||
|
-spec ensure_forward_present(id(), topic()) -> ok | {error, any()}.
|
||||||
|
ensure_forward_present(Id, Topic) -> gen_statem:call(id(Id), {ensure_forward_present, topic(Topic)}).
|
||||||
|
|
||||||
-spec get_subscriptions(id()) -> [{emqx_topic:topic(), qos()}].
|
-spec get_subscriptions(id()) -> [{emqx_topic:topic(), qos()}].
|
||||||
get_subscriptions(Id) -> gen_statem:call(id(Id), get_subscriptions).
|
get_subscriptions(Id) -> gen_statem:call(id(Id), get_subscriptions).
|
||||||
|
@ -185,7 +191,7 @@ init(Config) ->
|
||||||
batch_count_limit => GetQ(batch_count_limit, ?DEFAULT_BATCH_COUNT),
|
batch_count_limit => GetQ(batch_count_limit, ?DEFAULT_BATCH_COUNT),
|
||||||
max_inflight_batches => Get(max_inflight_batches, ?DEFAULT_SEND_AHEAD),
|
max_inflight_batches => Get(max_inflight_batches, ?DEFAULT_SEND_AHEAD),
|
||||||
mountpoint => format_mountpoint(Get(mountpoint, undefined)),
|
mountpoint => format_mountpoint(Get(mountpoint, undefined)),
|
||||||
topics => Topics,
|
forwards => Topics,
|
||||||
subscriptions => Subs,
|
subscriptions => Subs,
|
||||||
replayq => Queue,
|
replayq => Queue,
|
||||||
inflight => []
|
inflight => []
|
||||||
|
@ -274,6 +280,16 @@ connected(Type, Content, State) ->
|
||||||
%% Common handlers
|
%% Common handlers
|
||||||
common(_StateName, {call, From}, get_forwards, #{forwards := Forwards}) ->
|
common(_StateName, {call, From}, get_forwards, #{forwards := Forwards}) ->
|
||||||
{keep_state_and_data, [{reply, From, Forwards}]};
|
{keep_state_and_data, [{reply, From, Forwards}]};
|
||||||
|
common(_StateName, {call, From}, {ensure_forward_present, Topic},
|
||||||
|
#{forwards := Forwards} = State) ->
|
||||||
|
case lists:member(Topic, Forwards) of
|
||||||
|
true ->
|
||||||
|
{keep_state_and_data, [{reply, From, ok}]};
|
||||||
|
false ->
|
||||||
|
ok = subscribe_local_topic(Topic),
|
||||||
|
{keep_state, State#{forwards := lists:usort([Topic | Forwards])},
|
||||||
|
[{reply, From, ok}]}
|
||||||
|
end;
|
||||||
common(_StateName, {call, From}, get_subscriptions, #{subscriptions := Subs}) ->
|
common(_StateName, {call, From}, get_subscriptions, #{subscriptions := Subs}) ->
|
||||||
{keep_state_and_data, [{reply, From, Subs}]};
|
{keep_state_and_data, [{reply, From, Subs}]};
|
||||||
common(_StateName, info, {dispatch, _, Msg},
|
common(_StateName, info, {dispatch, _, Msg},
|
||||||
|
@ -281,7 +297,7 @@ common(_StateName, info, {dispatch, _, Msg},
|
||||||
NewQ = replayq:append(Q, collect([Msg])),
|
NewQ = replayq:append(Q, collect([Msg])),
|
||||||
{keep_state, State#{replayq => NewQ}, ?maybe_send};
|
{keep_state, State#{replayq => NewQ}, ?maybe_send};
|
||||||
common(StateName, Type, Content, State) ->
|
common(StateName, Type, Content, State) ->
|
||||||
?DEBUG("Portal ~p discarded ~p type event at state ~p:~p",
|
?INFO("Portal ~p discarded ~p type event at state ~p:~p",
|
||||||
[name(), Type, StateName, Content]),
|
[name(), Type, StateName, Content]),
|
||||||
{keep_state, State}.
|
{keep_state, State}.
|
||||||
|
|
||||||
|
@ -346,13 +362,19 @@ do_ack(#{inflight := Inflight}, Ref) ->
|
||||||
false -> stale
|
false -> stale
|
||||||
end.
|
end.
|
||||||
|
|
||||||
subscribe_local_topics(Topics) ->
|
subscribe_local_topics(Topics) -> lists:foreach(fun subscribe_local_topic/1, Topics).
|
||||||
lists:foreach(
|
|
||||||
fun(Topic0) ->
|
subscribe_local_topic(Topic0) ->
|
||||||
Topic = iolist_to_binary(Topic0),
|
Topic = topic(Topic0),
|
||||||
emqx_topic:validate({filter, Topic}) orelse erlang:error({bad_topic, Topic}),
|
try
|
||||||
emqx_broker:subscribe(Topic, #{qos => ?QOS_1, subid => name()})
|
emqx_topic:validate({filter, Topic})
|
||||||
end, Topics).
|
catch
|
||||||
|
error : Reason ->
|
||||||
|
erlang:error({bad_topic, Topic, Reason})
|
||||||
|
end,
|
||||||
|
ok = emqx_broker:subscribe(Topic, #{qos => ?QOS_1, subid => name()}).
|
||||||
|
|
||||||
|
topic(T) -> iolist_to_binary(T).
|
||||||
|
|
||||||
disconnect(#{connection := Conn,
|
disconnect(#{connection := Conn,
|
||||||
conn_ref := ConnRef,
|
conn_ref := ConnRef,
|
||||||
|
|
|
@ -54,10 +54,17 @@
|
||||||
"ECDH-RSA-AES128-SHA","AES128-SHA"]}]).
|
"ECDH-RSA-AES128-SHA","AES128-SHA"]}]).
|
||||||
|
|
||||||
run_setup_steps() ->
|
run_setup_steps() ->
|
||||||
|
_ = run_setup_steps([]),
|
||||||
|
%% return ok to be backward compatible
|
||||||
|
ok.
|
||||||
|
|
||||||
|
run_setup_steps(Config) ->
|
||||||
NewConfig = generate_config(),
|
NewConfig = generate_config(),
|
||||||
lists:foreach(fun set_app_env/1, NewConfig),
|
lists:foreach(fun set_app_env/1, NewConfig),
|
||||||
set_bridge_env(),
|
set_bridge_env(),
|
||||||
application:ensure_all_started(?APP).
|
{ok, _} = application:ensure_all_started(?APP),
|
||||||
|
set_log_level(Config),
|
||||||
|
Config.
|
||||||
|
|
||||||
run_teardown_steps() ->
|
run_teardown_steps() ->
|
||||||
?APP:shutdown().
|
?APP:shutdown().
|
||||||
|
@ -67,6 +74,12 @@ generate_config() ->
|
||||||
Conf = conf_parse:file([local_path(["etc", "gen.emqx.conf"])]),
|
Conf = conf_parse:file([local_path(["etc", "gen.emqx.conf"])]),
|
||||||
cuttlefish_generator:map(Schema, Conf).
|
cuttlefish_generator:map(Schema, Conf).
|
||||||
|
|
||||||
|
set_log_level(Config) ->
|
||||||
|
case proplists:get_value(log_level, Config) of
|
||||||
|
undefined -> ok;
|
||||||
|
Level -> emqx_logger:set_log_level(Level)
|
||||||
|
end.
|
||||||
|
|
||||||
get_base_dir(Module) ->
|
get_base_dir(Module) ->
|
||||||
{file, Here} = code:is_loaded(Module),
|
{file, Here} = code:is_loaded(Module),
|
||||||
filename:dirname(filename:dirname(Here)).
|
filename:dirname(filename:dirname(Here)).
|
||||||
|
|
|
@ -39,8 +39,7 @@ init_per_suite(Config) ->
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
emqx_ct_broker_helpers:run_setup_steps(),
|
emqx_ct_broker_helpers:run_setup_steps(Config).
|
||||||
Config.
|
|
||||||
|
|
||||||
end_per_suite(_Config) ->
|
end_per_suite(_Config) ->
|
||||||
emqx_ct_broker_helpers:run_teardown_steps().
|
emqx_ct_broker_helpers:run_teardown_steps().
|
||||||
|
@ -57,12 +56,14 @@ t_forwards_mngr(Config) when is_list(Config) ->
|
||||||
{ok, Pid} = emqx_portal:start_link(Name, Cfg),
|
{ok, Pid} = emqx_portal:start_link(Name, Cfg),
|
||||||
try
|
try
|
||||||
?assertEqual([<<"mngr">>], emqx_portal:get_forwards(Name)),
|
?assertEqual([<<"mngr">>], emqx_portal:get_forwards(Name)),
|
||||||
|
?assertEqual(ok, emqx_portal:ensure_forward_present(Name, "mngr")),
|
||||||
|
?assertEqual(ok, emqx_portal:ensure_forward_present(Name, "mngr2")),
|
||||||
|
?assertEqual([<<"mngr">>, <<"mngr2">>], emqx_portal:get_forwards(Pid)),
|
||||||
?assertEqual(Subs, emqx_portal:get_subscriptions(Pid))
|
?assertEqual(Subs, emqx_portal:get_subscriptions(Pid))
|
||||||
after
|
after
|
||||||
ok = emqx_portal:stop(Pid)
|
ok = emqx_portal:stop(Pid)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
%% A loopback RPC to local node
|
%% A loopback RPC to local node
|
||||||
t_rpc(Config) when is_list(Config) ->
|
t_rpc(Config) when is_list(Config) ->
|
||||||
Cfg = #{address => node(),
|
Cfg = #{address => node(),
|
||||||
|
|
Loading…
Reference in New Issue