Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

re #5 - handle reconnections for gen_bunny using a gen_bunny_mon modu…

…le. TODO: gen_bunny_mon unittests.
  • Loading branch information...
commit 7337b491ee7c79fe0c319814d9c6375b22d2dee4 1 parent 6c89cac
@dreid dreid authored
View
1  ebin/gen_bunny.app
@@ -7,6 +7,7 @@
bunnyc,
bunny_util,
gen_bunny,
+ gen_bunny_mon,
%% Unit tests
test_gb,
View
4 include/gen_bunny.hrl
@@ -37,9 +37,7 @@
connection_info,
declare_info,
consumer_tag,
- no_ack,
- channel_mon,
- connection_mon}).
+ no_ack}).
-record(bunnyc_state, {connection, channel, exchange, queue, key}).
View
92 src/gen_bunny.erl
@@ -66,6 +66,7 @@ start_link(Module, ConnectionInfo, DeclareInfo, InitArgs)
when is_atom(ConnectionInfo) orelse is_tuple(ConnectionInfo),
is_binary(DeclareInfo) orelse is_tuple(DeclareInfo),
is_list(InitArgs) ->
+ gen_bunny_mon:start_link(),
gen_server:start_link(
?MODULE,
[Module, ConnectionInfo, DeclareInfo, InitArgs],
@@ -84,30 +85,27 @@ cast(Dest, Request) ->
init([Module, ConnectionInfo, DeclareInfo, InitArgs0]) ->
{NoAck, InitArgs1} = get_opt(no_ack, InitArgs0, true),
{ConnectFun, InitArgs2} = get_opt(connect_fun, InitArgs1,
- fun bunny_util:connect/1),
+ fun gen_bunny_mon:connect/1),
{DeclareFun, InitArgs3} = get_opt(declare_fun, InitArgs2,
fun bunny_util:declare/2),
case Module:init(InitArgs3) of
{ok, ModState} ->
- case connect_declare_subscribe(
- ConnectFun, DeclareFun,
- ConnectionInfo, DeclareInfo, NoAck) of
- {ok, ConnectionPid, ChannelPid, QueueName} ->
- ChannelRef = erlang:monitor(process, ChannelPid),
- ConnectionRef = erlang:monitor(process, ConnectionPid),
+ case catch ConnectFun(ConnectionInfo) of
+ {ok, {ConnectionPid, ChannelPid}} ->
+ {ok, QueueName} = declare_subscribe(
+ ChannelPid, DeclareFun,
+ DeclareInfo, NoAck),
{ok, #gen_bunny_state{connect_fun=ConnectFun,
- declare_fun=DeclareFun,
- mod=Module,
- modstate=ModState,
- channel=ChannelPid,
- connection=ConnectionPid,
- connection_info=ConnectionInfo,
- declare_info=DeclareInfo,
- queue=QueueName,
- no_ack=NoAck,
- channel_mon=ChannelRef,
- connection_mon=ConnectionRef}};
+ declare_fun=DeclareFun,
+ mod=Module,
+ modstate=ModState,
+ channel=ChannelPid,
+ connection=ConnectionPid,
+ connection_info=ConnectionInfo,
+ declare_info=DeclareInfo,
+ queue=QueueName,
+ no_ack=NoAck}};
{_ErrClass, {error, Reason}} ->
Module:terminate(Reason, ModState),
{stop, Reason}
@@ -200,46 +198,16 @@ handle_info({Envelope=#'basic.deliver'{}, Message0},
handle_info(#'basic.consume_ok'{consumer_tag=CTag},
State=#gen_bunny_state{}) ->
{noreply, State#gen_bunny_state{consumer_tag=CTag}};
-handle_info({'DOWN', MonitorRef, process, _Object, _Info},
- State=#gen_bunny_state{channel_mon=ChannelRef,
- connection=Connection,
- declare_fun=DeclareFun,
- declare_info=DeclareInfo,
- no_ack=NoAck})
- when MonitorRef =:= ChannelRef ->
- true = erlang:demonitor(ChannelRef),
- Channel = amqp_connection:open_channel(Connection),
- NewChannelRef = erlang:monitor(process, Channel),
- {ok, QueueName} =
- declare_subscribe(
- Channel, DeclareFun, DeclareInfo, NoAck),
-
- {noreply, State#gen_bunny_state{queue=QueueName,
- channel=Channel,
- channel_mon=NewChannelRef}};
-handle_info({'DOWN', MonitorRef, process, _Object, _Info},
- State=#gen_bunny_state{channel_mon=ChannelRef,
- connection_mon=ConnectionRef,
- connect_fun=ConnectFun,
- connection_info=ConnectionInfo,
- declare_fun=DeclareFun,
- declare_info=DeclareInfo,
- no_ack=NoAck})
- when MonitorRef =:= ConnectionRef ->
- true = erlang:demonitor(ChannelRef),
- true = erlang:demonitor(ConnectionRef),
- {ok, NewConnection, NewChannel, QueueName} =
- connect_declare_subscribe(
- ConnectFun, DeclareFun, ConnectionInfo, DeclareInfo, NoAck),
-
- NewConnectionRef = erlang:monitor(process, NewConnection),
- NewChannelRef = erlang:monitor(process, NewChannel),
-
- {noreply, State#gen_bunny_state{queue=QueueName,
- connection=NewConnection,
- channel=NewChannel,
- channel_mon=NewChannelRef,
- connection_mon=NewConnectionRef}};
+handle_info({reconnected, {ConnectionPid, ChannelPid}},
+ State=#gen_bunny_state{declare_fun=DeclareFun,
+ declare_info=DeclareInfo,
+ no_ack=NoAck}) ->
+ {ok, QueueName} = declare_subscribe(ChannelPid, DeclareFun,
+ DeclareInfo, NoAck),
+
+ {noreply, State#gen_bunny_state{connection=ConnectionPid,
+ channel=ChannelPid,
+ queue=QueueName}};
handle_info(Info, State=#gen_bunny_state{mod=Module, modstate=ModState}) ->
case Module:handle_info(Info, ModState) of
{noreply, NewModState} ->
@@ -265,14 +233,8 @@ code_change(_OldVersion, State, _Extra) ->
%% TODO: support code changes?
{ok, State}.
-%% TODO: better error handling here.
-connect_declare_subscribe(ConnectFun, DeclareFun,
- ConnectionInfo, DeclareInfo, NoAck) ->
- {ok, {ConnectionPid, ChannelPid}} = ConnectFun(ConnectionInfo),
- {ok, QueueName} = declare_subscribe(ChannelPid, DeclareFun,
- DeclareInfo, NoAck),
- {ok, ConnectionPid, ChannelPid, QueueName}.
+%% TODO: better error handling here.
declare_subscribe(ChannelPid, DeclareFun, DeclareInfo, NoAck) ->
{ok, {_Exchange, Queue}} = DeclareFun(ChannelPid, DeclareInfo),
QueueName = bunny_util:get_name(Queue),
View
185 src/gen_bunny_mon.erl
@@ -0,0 +1,185 @@
+%% The MIT License
+
+%% Copyright (c) David Reid <dreid@dreid.org>
+
+%% Permission is hereby granted, free of charge, to any person obtaining a copy
+%% of this software and associated documentation files (the "Software"), to deal
+%% in the Software without restriction, including without limitation the rights
+%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+%% copies of the Software, and to permit persons to whom the Software is
+%% furnished to do so, subject to the following conditions:
+
+%% The above copyright notice and this permission notice shall be included in
+%% all copies or substantial portions of the Software.
+
+%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+%% THE SOFTWARE.
+-module(gen_bunny_mon).
+-author('David Reid <dreid@dreid.org').
+-behaviour(gen_server).
+
+-define(SERVER, ?MODULE).
+
+-define(RECONNECT_DELAY, timer:seconds(1)).
+
+-record(gen_bunny_mon,
+ {
+ connections=dict:new(),
+ connect_fun
+ }).
+
+-record(connection,
+ {
+ consumer,
+ info
+ }).
+
+%% ------------------------------------------------------------------
+%% API Function Exports
+%% ------------------------------------------------------------------
+
+-export([start_link/0, start_link/1, connect/1, get_state/0]).
+
+%% ------------------------------------------------------------------
+%% gen_server Function Exports
+%% ------------------------------------------------------------------
+
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
+ code_change/3]).
+
+%% ------------------------------------------------------------------
+%% API Function Definitions
+%% ------------------------------------------------------------------
+
+start_link() ->
+ start_link(fun bunny_util:connect/1).
+
+start_link(ConnectFun) ->
+ gen_server:start_link({local, ?SERVER}, ?MODULE,
+ [ConnectFun],
+ []).
+
+connect(ConnectionInfo) ->
+ gen_server:call(?SERVER, {connect, self(), ConnectionInfo}).
+
+get_state() ->
+ gen_server:call(?SERVER, get_state).
+%% ------------------------------------------------------------------
+%% gen_server Function Definitions
+%% ------------------------------------------------------------------
+
+init([ConnectFun]) ->
+ {ok, #gen_bunny_mon{connect_fun=ConnectFun}}.
+
+handle_call(get_state, _From, State) ->
+ {reply, {ok, State}, State};
+handle_call({connect, ConsumerPid, ConnectionInfo}, From, State) ->
+ case do_connect(ConsumerPid, ConnectionInfo, State) of
+ {{ok, {ConnectionPid, ChannelPid}}, State1} ->
+ {reply, {ok, {ConnectionPid, ChannelPid}}, State1};
+ {{connection_error, Error}, State1} ->
+ error_logger:error_report(
+ ["Could not connect, scheduling reconnect.",
+ {error, Error}]),
+
+ NotifyOnConnect = fun(Pids) ->
+ gen_server:reply(From, {ok, Pids})
+ end,
+
+ schedule_reconnect(ConsumerPid, ConnectionInfo, NotifyOnConnect),
+ {noreply, State1}
+ end;
+handle_call(_Request, _From, State) ->
+ {noreply, ok, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info({'DOWN', ConnectionRef, process, _Object, _Info}, State) ->
+ {Connection, State1} = remove_connection(ConnectionRef, State),
+
+ ConsumerPid = Connection#connection.consumer,
+ ConnectionInfo = Connection#connection.info,
+
+ NotifyOnConnect = fun(Pids) ->
+ ConsumerPid ! {reconnected, Pids}
+ end,
+
+ schedule_reconnect(ConsumerPid, ConnectionInfo, NotifyOnConnect),
+ {noreply, State1};
+handle_info({reconnect,
+ ConsumerPid, ConnectionInfo,
+ NotifyOnConnect},
+ State) ->
+ State2 = case do_connect(ConsumerPid, ConnectionInfo, State) of
+ {{ok, {ConnectionPid, ChannelPid}}, State1} ->
+ NotifyOnConnect({ConnectionPid, ChannelPid}),
+ State1;
+ {{connection_error, Error}, State1} ->
+ error_logger:error_report(
+ ["Could not connect, scheduling reconnect.",
+ {error, Error}]),
+ schedule_reconnect(
+ ConsumerPid, ConnectionInfo, NotifyOnConnect),
+ State1
+ end,
+
+ {noreply, State2};
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%% ------------------------------------------------------------------
+%% Internal Function Definitions
+%% ------------------------------------------------------------------
+add_connection(ConsumerPid, ConnectionPid, ConnectionInfo,
+ State=#gen_bunny_mon{connections=Connections}) ->
+ ConnectionRef = erlang:monitor(process, ConnectionPid),
+
+ State#gen_bunny_mon{
+ connections=dict:store(ConnectionRef,
+ #connection{consumer=ConsumerPid,
+ info=ConnectionInfo},
+ Connections)}.
+
+
+remove_connection(ConnectionRef,
+ State=#gen_bunny_mon{connections=Connections}) ->
+ true = erlang:demonitor(ConnectionRef),
+
+ {ok, Connection} = dict:find(ConnectionRef, Connections),
+ NewConnections = dict:erase(ConnectionRef, Connections),
+
+ {Connection, State#gen_bunny_mon{
+ connections=NewConnections}}.
+
+
+schedule_reconnect(ConsumerPid, ConnectionInfo, NotifyOnConnect) ->
+ timer:send_after(?RECONNECT_DELAY,
+ {reconnect,
+ ConsumerPid, ConnectionInfo, NotifyOnConnect}).
+
+
+do_connect(ConsumerPid, ConnectionInfo,
+ State=#gen_bunny_mon{connect_fun=ConnectFun}) ->
+ try
+ {ok, {ConnectionPid, ChannelPid}} = ConnectFun(ConnectionInfo),
+ {{ok, {ConnectionPid, ChannelPid}}, add_connection(
+ ConsumerPid, ConnectionPid,
+ ConnectionInfo,
+ State)}
+ catch
+ Type:What ->
+ {{connection_error, {{Type, What, erlang:get_stacktrace()},
+ {connection_info, ConnectionInfo}}}, State}
+ end.
View
195 src/gen_bunny_tests.erl
@@ -2,19 +2,20 @@
-include_lib("gen_bunny.hrl").
-include_lib("eunit/include/eunit.hrl").
-cds_setup() ->
+declare_subscribe_setup() ->
{ok, _} = mock:mock(amqp_channel),
ok.
-cds_stop(_) ->
+declare_subscribe_stop(_) ->
mock:verify_and_stop(amqp_channel),
ok.
-cds_expects(_DummyConn, DummyChannel, NoAck) ->
+declare_subscribe_expects(DummyChannel, NoAck) ->
mock:expects(amqp_channel, subscribe,
fun({Chan,
- #'basic.consume'{queue= <<"cds.test">>, no_ack=NA},
+ #'basic.consume'{queue= <<"declare_subscribe.test">>,
+ no_ack=NA},
_Pid})
when Chan =:= DummyChannel,
NA =:= NoAck ->
@@ -23,46 +24,38 @@ cds_expects(_DummyConn, DummyChannel, NoAck) ->
ok),
ok.
-cds_funs(DummyConn, DummyChannel) ->
- ConnectFun = fun(direct) ->
- {ok, {DummyConn, DummyChannel}}
- end,
-
- DeclareFun = fun(Chan, <<"cds.test">>) when Chan =:= DummyChannel ->
- {ok, {bunny_util:new_exchange(<<"cds.test">>),
- bunny_util:new_queue(<<"cds.test">>)}}
- end,
-
- {ConnectFun, DeclareFun}.
+declare_subscribe_funs(DummyChannel) ->
+ fun(Chan, <<"declare_subscribe.test">>) when Chan =:= DummyChannel ->
+ {ok, {bunny_util:new_exchange(<<"declare_subscribe.test">>),
+ bunny_util:new_queue(<<"declare_subscribe.test">>)}}
+ end.
-cds_test_() ->
- DummyConn = c:pid(0,0,0),
+declare_subscribe_test_() ->
DummyChannel = c:pid(0,0,1),
- {ConnectFun, DeclareFun} = cds_funs(DummyConn, DummyChannel),
+ DeclareFun = declare_subscribe_funs(DummyChannel),
- {setup, fun cds_setup/0, fun cds_stop/1,
+ {setup, fun declare_subscribe_setup/0, fun declare_subscribe_stop/1,
?_test(
[begin
- cds_expects(DummyConn, DummyChannel, false),
- gen_bunny:connect_declare_subscribe(
- ConnectFun, DeclareFun,
- direct, <<"cds.test">>, false)
+ declare_subscribe_expects(DummyChannel, false),
+ gen_bunny:declare_subscribe(
+ DummyChannel, DeclareFun,
+ <<"declare_subscribe.test">>, false)
end])}.
-cds_noack_test_() ->
- DummyConn = c:pid(0,0,0),
+declare_subscribe_noack_test_() ->
DummyChannel = c:pid(0,0,1),
- {ConnectFun, DeclareFun} = cds_funs(DummyConn, DummyChannel),
+ DeclareFun = declare_subscribe_funs(DummyChannel),
- {setup, fun cds_setup/0, fun cds_stop/1,
+ {setup, fun declare_subscribe_setup/0, fun declare_subscribe_stop/1,
?_test(
[begin
- cds_expects(DummyConn, DummyChannel, true),
- gen_bunny:connect_declare_subscribe(
- ConnectFun, DeclareFun,
- direct, <<"cds.test">>, true)
+ declare_subscribe_expects(DummyChannel, true),
+ gen_bunny:declare_subscribe(
+ DummyChannel, DeclareFun,
+ <<"declare_subscribe.test">>, true)
end])}.
@@ -114,14 +107,13 @@ test_gb_noack_false_setup() ->
test_gb_stop({_ConnectionPid, _ChannelPid, TestPid}) ->
ExpectedChannelPid = gen_bunny:get_channel(TestPid),
ExpectedConnectionPid = gen_bunny:get_connection(TestPid),
-
mock:expects(amqp_channel, call,
fun({Channel, #'basic.cancel'{
consumer_tag= <<"bunny.consumer">>}})
when Channel =:= ExpectedChannelPid ->
true
end,
- ok),
+ ok, 1),
mock:expects(amqp_connection, close,
fun({Connection})
@@ -138,7 +130,7 @@ test_gb_stop({_ConnectionPid, _ChannelPid, TestPid}) ->
ok),
gen_bunny:stop(TestPid),
- timer:sleep(100), %% I hate this.
+ timer:sleep(500),
mock:verify_and_stop(amqp_channel),
mock:verify_and_stop(amqp_connection),
ok.
@@ -148,7 +140,8 @@ test_gb_start_link_test_() ->
fun({ConnectionPid, ChannelPid, TestPid}) ->
?_test(
[begin
- ?assertEqual(ConnectionPid, gen_bunny:get_connection(TestPid)),
+ ?assertEqual(ConnectionPid,
+ gen_bunny:get_connection(TestPid)),
?assertEqual(ChannelPid, gen_bunny:get_channel(TestPid)),
?assertEqual(<<"bunny.consumer">>,
gen_bunny:get_consumer_tag(TestPid))
@@ -237,35 +230,34 @@ test_gb_info_passthrough_test_() ->
end])
end}.
-test_monitor_setup() ->
+
+test_reconnected_gb_setup() ->
{ok, _} = mock:mock(amqp_channel),
{ok, _} = mock:mock(amqp_connection),
ConnectionPid = spawn_fake_proc(),
- NewConnectionPid = spawn_fake_proc(),
-
ChannelPid = spawn_fake_proc(),
+
+ NewConnectionPid = spawn_fake_proc(),
NewChannelPid = spawn_fake_proc(),
mock:expects(amqp_channel, subscribe,
- fun({_Channel,
- #'basic.consume'{queue= <<"bunny.test">>},
- _Pid}) ->
- true
+ fun({Channel,
+ #'basic.consume'{queue= <<"bunny.test">>},
+ _Pid})
+ when Channel =:= ChannelPid orelse
+ Channel =:= NewChannelPid ->
+ true
end,
ok, 2),
ConnectFun = fun(direct) ->
- case get('_connect_fun_run_before') of
- undefined ->
- put('_connect_fun_run_before', true),
- {ok, {ConnectionPid, ChannelPid}};
- true ->
- {ok, {NewConnectionPid, NewChannelPid}}
- end
+ {ok, {ConnectionPid, ChannelPid}}
end,
- DeclareFun = fun(_Channel, <<"bunny.test">>) ->
+ DeclareFun = fun(Channel, <<"bunny.test">>)
+ when Channel =:= ChannelPid orelse
+ Channel =:= NewChannelPid ->
{ok, {bunny_util:new_exchange(<<"bunny.test">>),
bunny_util:new_queue(<<"bunny.test">>)}}
end,
@@ -275,107 +267,30 @@ test_monitor_setup() ->
TestPid ! #'basic.consume_ok'{consumer_tag = <<"bunny.consumer">>},
- {ConnectionPid, NewConnectionPid, ChannelPid, NewChannelPid, TestPid}.
-
-test_monitor_stop({_ConnectionPid, _NewConnectionPid,
- _ChannelPid, _NewChannelPid, TestPid}) ->
- ExpectedChannelPid = gen_bunny:get_channel(TestPid),
- ExpectedConnectionPid = gen_bunny:get_connection(TestPid),
-
- mock:expects(amqp_channel, call,
- fun({Channel, #'basic.cancel'{
- consumer_tag= <<"bunny.consumer">>}})
- when Channel =:= ExpectedChannelPid ->
- true
- end,
- ok),
-
- mock:expects(amqp_connection, close,
- fun({Connection})
- when Connection =:= ExpectedConnectionPid ->
- true
- end,
- ok),
+ {ConnectionPid, ChannelPid, NewConnectionPid, NewChannelPid, TestPid}.
- mock:expects(amqp_channel, close,
- fun({Channel})
- when Channel =:= ExpectedChannelPid ->
- true
- end,
- ok),
- gen_bunny:stop(TestPid),
- timer:sleep(100), %% I hate this.
- mock:verify_and_stop(amqp_channel),
- mock:verify_and_stop(amqp_connection),
- ok.
-
-channel_monitor_test_() ->
- {setup, fun test_monitor_setup/0, fun test_monitor_stop/1,
- fun({ConnectionPid, _, ChannelPid, NewChannelPid, TestPid}) ->
- ?_test(
- [begin
- MonRef = erlang:monitor(process, ChannelPid),
-
- mock:expects(
- amqp_connection, open_channel,
- fun({Connection})
- when is_pid(Connection) andalso
- Connection =:= ConnectionPid ->
- true
- end,
- fun(_, _) ->
- NewChannelPid
- end),
-
- exit(ChannelPid, die),
- ?assertEqual(true, erlang:is_process_alive(TestPid)),
- ?assertEqual(false, erlang:is_process_alive(ChannelPid)),
-
- receive
- {'DOWN', MonRef, process, ChannelPid, die} ->
- ok
- end,
-
- ?assertMatch(NewChannelPid,
- gen_bunny:get_channel(TestPid)),
- ?assert(ChannelPid =/= NewChannelPid),
- ?assertEqual(true, erlang:is_process_alive(NewChannelPid))
- end])
- end}.
+test_reconnected_gb_stop({ConnectionPid, ChannelPid, _, _, TestPid}) ->
+ test_gb_stop({ConnectionPid, ChannelPid, TestPid}).
-connection_monitor_test_() ->
- {setup, fun test_monitor_setup/0, fun test_monitor_stop/1,
- fun({ConnectionPid, NewConnectionPid,
- ChannelPid, NewChannelPid, TestPid}) ->
+test_gb_reconnected_test_() ->
+ {setup, fun test_reconnected_gb_setup/0, fun test_reconnected_gb_stop/1,
+ fun({_ConnectionPid, _ChannelPid,
+ NewConnectionPid, NewChannelPid, TestPid}) ->
?_test(
[begin
- MonRef = erlang:monitor(process, ConnectionPid),
+ TestPid ! {reconnected,
+ {NewConnectionPid, NewChannelPid}},
- exit(ConnectionPid, die),
- ?assertEqual(true, erlang:is_process_alive(TestPid)),
- ?assertEqual(false,
- erlang:is_process_alive(ConnectionPid)),
-
- receive
- {'DOWN', MonRef, process, ConnectionPid, die} ->
- ok
- end,
-
- ?assertMatch(NewConnectionPid,
+ ?assertEqual(NewConnectionPid,
gen_bunny:get_connection(TestPid)),
- ?assert(ConnectionPid =/= NewConnectionPid),
- ?assertEqual(true,
- erlang:is_process_alive(NewConnectionPid)),
-
- ?assertMatch(NewChannelPid,
- gen_bunny:get_channel(TestPid)),
- ?assert(ChannelPid =/= NewChannelPid),
- ?assertEqual(true, erlang:is_process_alive(NewChannelPid))
+ ?assertEqual(NewChannelPid,
+ gen_bunny:get_channel(TestPid))
end])
end}.
+
test_crash_setup() ->
{ok, _} = mock:mock(amqp_channel),
{ok, _} = mock:mock(amqp_connection),

0 comments on commit 7337b49

Please sign in to comment.
Something went wrong with that request. Please try again.