Created the irc_object_supervisor, which is created by the irc_conn startup
authorMatt Mullins <mmullins@mmlx.us>
Thu, 1 Sep 2011 01:25:18 +0000 (20:25 -0500)
committerMatt Mullins <mmullins@mmlx.us>
Thu, 1 Sep 2011 01:25:18 +0000 (20:25 -0500)
irc/irc_conn.erl
irc/irc_net_sup.erl
irc/irc_object_sup.erl [new file with mode: 0644]

index f18551b..db68f7d 100644 (file)
@@ -34,6 +34,11 @@ start_link(Instance, Supervisor, TableId) ->
 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]),
@@ -57,7 +62,14 @@ handle_cast({send_command, Command}, State) ->
     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 }) ->
index f9f6e65..4938c41 100644 (file)
@@ -7,7 +7,8 @@
 -behavior(supervisor).
 
 -export([
-          start_link/1
+          start_link/1,
+          create_object_sup/3
                ]).
 -export([init/1]).
 
@@ -28,3 +29,15 @@ init(Instance) ->
        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}.
diff --git a/irc/irc_object_sup.erl b/irc/irc_object_sup.erl
new file mode 100644 (file)
index 0000000..b301e3e
--- /dev/null
@@ -0,0 +1,30 @@
+%% @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).