parent
72791b569e
commit
9a2573d54b
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved.
|
%% Copyright (c) 2018 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||||
%%
|
%%
|
||||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@ -122,76 +121,9 @@ init([Options]) ->
|
||||||
options = Options,
|
options = Options,
|
||||||
reconnect_interval = ReconnectInterval}}.
|
reconnect_interval = ReconnectInterval}}.
|
||||||
|
|
||||||
handle_call(start_bridge, _From, State = #state{options = Options,
|
handle_call(start_bridge, _From, State = #state{client_pid = undefined}) ->
|
||||||
replayq = undefined,
|
{Msg, NewState} = bridge(start, State),
|
||||||
client_pid = undefined,
|
{reply, #{msg => Msg}, NewState};
|
||||||
queue_option = #{batch_size := BatchSize,
|
|
||||||
replayq_dir := ReplayqDir,
|
|
||||||
replayq_seg_bytes := ReplayqSegBytes}}) ->
|
|
||||||
case emqx_client:start_link([{owner, self()}|options(Options)]) of
|
|
||||||
{ok, ClientPid} ->
|
|
||||||
case emqx_client:connect(ClientPid) of
|
|
||||||
{ok, _} ->
|
|
||||||
emqx_logger:info("[Bridge] connected to remote successfully"),
|
|
||||||
Subs = subscribe_remote_topics(ClientPid, get_value(subscriptions, Options, [])),
|
|
||||||
Forwards = subscribe_local_topics(Options),
|
|
||||||
ReplayQ = replayq:open(#{dir => ReplayqDir,
|
|
||||||
seg_bytes => ReplayqSegBytes,
|
|
||||||
sizer => fun(Term) ->
|
|
||||||
size(term_to_binary(Term))
|
|
||||||
end,
|
|
||||||
marshaller => fun({PktId, Msg}) ->
|
|
||||||
term_to_binary({PktId, Msg});
|
|
||||||
(Bin) ->
|
|
||||||
binary_to_term(Bin)
|
|
||||||
end
|
|
||||||
}),
|
|
||||||
{NewReplayQ, AckRef, ReadQ} = replayq:pop(ReplayQ, #{count_limit => BatchSize}),
|
|
||||||
{ok, NewReadQ} = publish_readq_msg(ClientPid, ReadQ, []),
|
|
||||||
{reply, #{msg => <<"start bridge successfully">>}, State#state{client_pid = ClientPid,
|
|
||||||
subscriptions = Subs,
|
|
||||||
readq = NewReadQ,
|
|
||||||
replayq = NewReplayQ,
|
|
||||||
ackref = AckRef,
|
|
||||||
forwards = Forwards}};
|
|
||||||
{error, Reason} ->
|
|
||||||
emqx_logger:error("[Bridge] connect to remote failed! error: ~p", [Reason]),
|
|
||||||
{reply, #{msg => <<"connect to remote failed">>}, State#state{client_pid = ClientPid}}
|
|
||||||
end;
|
|
||||||
{error, Reason} ->
|
|
||||||
emqx_logger:error("[Bridge] start failed! error: ~p", [Reason]),
|
|
||||||
{reply, #{msg => <<"start bridge failed">>}, State}
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
handle_call(start_bridge, _From, State = #state{options = Options,
|
|
||||||
client_pid = undefined,
|
|
||||||
replayq = ReplayQ,
|
|
||||||
queue_option = #{batch_size := BatchSize}
|
|
||||||
}) ->
|
|
||||||
case emqx_client:start_link([{owner, self()} | options(Options)]) of
|
|
||||||
{ok, ClientPid} ->
|
|
||||||
case emqx_client:connect(ClientPid) of
|
|
||||||
{ok, _} ->
|
|
||||||
emqx_logger:info("[Bridge] connected to remote ysucessfully"),
|
|
||||||
Subs = subscribe_remote_topics(ClientPid, get_value(subscriptions, Options, [])),
|
|
||||||
Forwards = subscribe_local_topics(Options),
|
|
||||||
{NewReplayQ, AckRef, ReadQ} = replayq:pop(ReplayQ, #{count_limit => BatchSize}),
|
|
||||||
{ok, NewReadQ} = publish_readq_msg(ClientPid, ReadQ, []),
|
|
||||||
{reply, #{msg => <<"start bridge successfully">>}, State#state{client_pid = ClientPid,
|
|
||||||
subscriptions = Subs,
|
|
||||||
readq = NewReadQ,
|
|
||||||
replayq = NewReplayQ,
|
|
||||||
ackref = AckRef,
|
|
||||||
forwards = Forwards}};
|
|
||||||
{error, Reason} ->
|
|
||||||
emqx_logger:error("[Bridge] connect to remote failed! error: ~p", [Reason]),
|
|
||||||
{reply, #{msg => <<"connect to remote failed">>}, State#state{client_pid = ClientPid}}
|
|
||||||
end;
|
|
||||||
{error, Reason} ->
|
|
||||||
emqx_logger:error("[Bridge] restart failed! error: ~p", [Reason]),
|
|
||||||
{reply, #{msg => <<"start bridge failed">>}, State}
|
|
||||||
end;
|
|
||||||
|
|
||||||
handle_call(start_bridge, _From, State) ->
|
handle_call(start_bridge, _From, State) ->
|
||||||
{reply, #{msg => <<"bridge already started">>}, State};
|
{reply, #{msg => <<"bridge already started">>}, State};
|
||||||
|
@ -258,34 +190,16 @@ handle_cast(Msg, State) ->
|
||||||
emqx_logger:error("[Bridge] unexpected cast: ~p", [Msg]),
|
emqx_logger:error("[Bridge] unexpected cast: ~p", [Msg]),
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
handle_info(restart, State = #state{options = Options,
|
%%----------------------------------------------------------------
|
||||||
client_pid = undefined,
|
%% Start or restart bridge
|
||||||
replayq = ReplayQ,
|
%%----------------------------------------------------------------
|
||||||
queue_option = #{batch_size := BatchSize}
|
handle_info(start, State) ->
|
||||||
}) ->
|
{_Msg, NewState} = bridge(start, State),
|
||||||
case emqx_client:start_link([{owner, self()} | options(Options)]) of
|
{noreply, NewState};
|
||||||
{ok, ClientPid} ->
|
|
||||||
case emqx_client:connect(ClientPid) of
|
handle_info(restart, State) ->
|
||||||
{ok, _} ->
|
{_Msg, NewState} = bridge(restart, State),
|
||||||
emqx_logger:info("[Bridge] connected to remote successfully"),
|
{noreply, NewState};
|
||||||
Subs = subscribe_remote_topics(ClientPid, get_value(subscriptions, Options, [])),
|
|
||||||
Forwards = subscribe_local_topics(Options),
|
|
||||||
{NewReplayQ, AckRef, ReadQ} = replayq:pop(ReplayQ, #{count_limit => BatchSize}),
|
|
||||||
{ok, NewReadQ} = publish_readq_msg(ClientPid, ReadQ, []),
|
|
||||||
{noreply, State#state{client_pid = ClientPid,
|
|
||||||
subscriptions = Subs,
|
|
||||||
readq = NewReadQ,
|
|
||||||
replayq = NewReplayQ,
|
|
||||||
ackref = AckRef,
|
|
||||||
forwards = Forwards}};
|
|
||||||
{error, Reason} ->
|
|
||||||
emqx_logger:error("[Bridge] connect to remote failed! error: ~p", [Reason]),
|
|
||||||
{noreply, State#state{client_pid = ClientPid}}
|
|
||||||
end;
|
|
||||||
{error, Reason} ->
|
|
||||||
emqx_logger:error("[Bridge] restart failed! error: ~p", [Reason]),
|
|
||||||
{noreply, State}
|
|
||||||
end;
|
|
||||||
|
|
||||||
%%----------------------------------------------------------------
|
%%----------------------------------------------------------------
|
||||||
%% pop message from replayq and publish again
|
%% pop message from replayq and publish again
|
||||||
|
@ -296,7 +210,7 @@ handle_info(pop, State = #state{writeq = WriteQ, replayq = ReplayQ,
|
||||||
{NewReadQ1, NewWriteQ} = case NewReadQ of
|
{NewReadQ1, NewWriteQ} = case NewReadQ of
|
||||||
[] -> {WriteQ, []};
|
[] -> {WriteQ, []};
|
||||||
_ -> {NewReadQ, WriteQ}
|
_ -> {NewReadQ, WriteQ}
|
||||||
end,
|
end,
|
||||||
self() ! replay,
|
self() ! replay,
|
||||||
{noreply, State#state{readq = NewReadQ1, writeq = NewWriteQ, replayq = NewReplayQ, ackref = AckRef}};
|
{noreply, State#state{readq = NewReadQ1, writeq = NewWriteQ, replayq = NewReplayQ, ackref = AckRef}};
|
||||||
|
|
||||||
|
@ -464,3 +378,49 @@ delete(PktId, State = #state{readq = [], writeq = WriteQ}) ->
|
||||||
|
|
||||||
delete(PktId, State = #state{readq = ReadQ}) ->
|
delete(PktId, State = #state{readq = ReadQ}) ->
|
||||||
State#state{readq = lists:keydelete(PktId, 1, ReadQ)}.
|
State#state{readq = lists:keydelete(PktId, 1, ReadQ)}.
|
||||||
|
|
||||||
|
bridge(Action, State = #state{options = Options,
|
||||||
|
replayq = ReplayQ,
|
||||||
|
queue_option = QueueOption}) ->
|
||||||
|
case emqx_client:start_link([{owner, self()}|options(Options)]) of
|
||||||
|
{ok, ClientPid} ->
|
||||||
|
case emqx_client:connect(ClientPid) of
|
||||||
|
{ok, _} ->
|
||||||
|
emqx_logger:info("[Bridge] connected to remote successfully"),
|
||||||
|
Subs = subscribe_remote_topics(ClientPid, get_value(subscriptions, Options, [])),
|
||||||
|
Forwards = subscribe_local_topics(Options),
|
||||||
|
{NewReplayQ, AckRef, ReadQ} = open_replayq(ReplayQ, QueueOption),
|
||||||
|
{ok, NewReadQ} = publish_readq_msg(ClientPid, ReadQ, []),
|
||||||
|
{<<"start bridge successfully">>,
|
||||||
|
State#state{client_pid = ClientPid,
|
||||||
|
subscriptions = Subs,
|
||||||
|
readq = NewReadQ,
|
||||||
|
replayq = NewReplayQ,
|
||||||
|
ackref = AckRef,
|
||||||
|
forwards = Forwards}};
|
||||||
|
{error, Reason} ->
|
||||||
|
emqx_logger:error("[Bridge] connect to remote failed! error: ~p", [Reason]),
|
||||||
|
{<<"connect to remote failed">>,
|
||||||
|
State#state{client_pid = ClientPid}}
|
||||||
|
end;
|
||||||
|
{error, Reason} ->
|
||||||
|
emqx_logger:error("[Bridge] ~p failed! error: ~p", [Action, Reason]),
|
||||||
|
{<<"start bridge failed">>, State}
|
||||||
|
end.
|
||||||
|
|
||||||
|
open_replayq(undefined, #{batch_size := BatchSize,
|
||||||
|
replayq_dir := ReplayqDir,
|
||||||
|
replayq_seg_bytes := ReplayqSegBytes}) ->
|
||||||
|
ReplayQ = replayq:open(#{dir => ReplayqDir,
|
||||||
|
seg_bytes => ReplayqSegBytes,
|
||||||
|
sizer => fun(Term) ->
|
||||||
|
size(term_to_binary(Term))
|
||||||
|
end,
|
||||||
|
marshaller => fun({PktId, Msg}) ->
|
||||||
|
term_to_binary({PktId, Msg});
|
||||||
|
(Bin) ->
|
||||||
|
binary_to_term(Bin)
|
||||||
|
end}),
|
||||||
|
replayq:pop(ReplayQ, #{count_limit => BatchSize});
|
||||||
|
open_replayq(ReplayQ, #{batch_size := BatchSize}) ->
|
||||||
|
replayq:pop(ReplayQ, #{count_limit => BatchSize}).
|
||||||
|
|
Loading…
Reference in New Issue