From: Matt Mullins Date: Thu, 1 Sep 2011 01:25:18 +0000 (-0500) Subject: Created the irc_object_supervisor, which is created by the irc_conn startup X-Git-Tag: v5~12 X-Git-Url: http://git.mmlx.us/?a=commitdiff_plain;h=cc9c85e2c0a441073c87c8af545490a7aa451ac8;p=erlbot.git Created the irc_object_supervisor, which is created by the irc_conn startup --- diff --git a/irc/irc_conn.erl b/irc/irc_conn.erl index f18551b..db68f7d 100644 --- a/irc/irc_conn.erl +++ b/irc/irc_conn.erl @@ -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 }) -> diff --git a/irc/irc_net_sup.erl b/irc/irc_net_sup.erl index f9f6e65..4938c41 100644 --- a/irc/irc_net_sup.erl +++ b/irc/irc_net_sup.erl @@ -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 index 0000000..b301e3e --- /dev/null +++ b/irc/irc_object_sup.erl @@ -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).