init({Instance, Supervisor, TableId}) ->
ets:insert(TableId, {irc_conn_pid, self()}), % record the connection PID in the table
+ gen_server:cast(self(), create_object_sup), % This process is tasked with creating
+ % the irc_object_sup, but we defer until
+ % after init() finishes to avoid deadlock
+ % on the supervisor's mailbox
+
{Instance, Config} = lists:keyfind(Instance, 1, config:get_config(irc)),
{Host, Port, Nick, Realname, _Channels} = Config,
{ok, Socket} = gen_tcp:connect(Host, Port, [list]),
gen_tcp:send(State#irc_state.socket,
irc_util:command_to_list(Command) ++ "\r\n"
),
- {noreply, State}.
+ {noreply, State};
+
+handle_cast(create_object_sup, State) ->
+ #irc_state{ instance = Instance,
+ supervisor = Supervisor,
+ table_id = TableId } = State,
+ {ok, ObjectSupPid} = irc_net_sup:create_object_sup(Instance, Supervisor, TableId),
+ {noreply, State#irc_state{ object_sup = ObjectSupPid }}.
%% Handle incoming data
handle_info({tcp, _Socket, Data}, State = #irc_state{ socket = _Socket }) ->
-behavior(supervisor).
-export([
- start_link/1
+ start_link/1,
+ create_object_sup/3
]).
-export([init/1]).
RestartStrategy = {one_for_all, 5, 60}, % Die if a child dies more than 5
% times in 60 seconds.
{ok, {RestartStrategy, Children}}.
+
+%% @doc Creates the irc_object_sup supervisor as a child of this supervisor
+create_object_sup(Instance, Supervisor, TableId) ->
+ ObjectSup = {object_sup,
+ {irc_object_sup, start_link, [Instance, Supervisor, TableId]},
+ permanent,
+ 5,
+ supervisor,
+ [irc_object_sup]
+ },
+ {ok, ObjectSupPid} = supervisor:start_child(Supervisor, ObjectSup),
+ {ok, ObjectSupPid}.
--- /dev/null
+%% @doc Supervises the ancillary processes associated with an IRC connection,
+%% such as workers that track IRC channel state, listen for AMQP messages, etc.
+
+-module(irc_object_sup).
+-behavior(supervisor).
+
+-export([
+ start_link/3,
+ add_amqp_listener/3
+ ]).
+-export([init/1]).
+
+start_link(Instance, Supervisor, TableId) ->
+ supervisor:start_link(?MODULE, {Instance, Supervisor, TableId}).
+
+init({_Instance, _Supervisor, _TableId}) ->
+ Children = [],
+ RestartStrategy = {one_for_one, 5, 60},
+ {ok, {RestartStrategy, Children}}.
+
+add_amqp_listener(ObjectSup, ConnectionPid, Channel) ->
+ Child = {"amqp_" ++ Channel,
+ % TODO: ↓ fix the routing key
+ {irc_amqp_listener, start_link, [ConnectionPid, Channel, "foobar"]},
+ transient,
+ brutal_kill,
+ worker,
+ [irc_amqp_listener]
+ },
+ supervisor:start_child(ObjectSup, Child).