[erlang-questions] non-trivial supervisor idioms?

Edmond Begumisa <>
Mon Sep 27 19:12:33 CEST 2010


Hi Daniel,

IMO, your first suggestion (having the supervisor create a connection in  
init()) I think would be a bad idea. My understanding of OTP design  
principles is that the supervisor itself shouldn't do any actual work, it  
should only keep an eye on others who do do the work.

Your second suggestion would be much better. I'd approach it like Essien,  
but I'd also wrap the call supervisor:start_child(ChanSup, [Connection])  
in a function exported from the supervisor module...

new_child(ChanSup, [Connection])
   supervisor:start_child(ChanSup, [Connection]).

To reinforce what Essien said, your connection would 'ask' the supervisor  
to 'create and keep an eye on' a new channel.

- Edmond -

On Tue, 28 Sep 2010 02:38:23 +1000, Essien Essien <>  
wrote:

> Hi Dan,
>
> <snip>
>
>> Thanks, I forgot about start phases.  Makes perfect sense for mnesia  
>> init.
>>
>> Now how about this scenario:  I am opening an ssh client connection  
>> which
>> will have multiple channels.  The channel processes require a connection
>> reference, so I have to establish the connection before creating them.  
>>  I
>> will keep these channel processes under a supervisor.  Now, I have the
>> choice of establishing the connection in supervisor init() and then
>> returning  childspecs with the connection reference built-in,or  
>> creating a
>> worker to establish the connection and then dynamically add channel
>> processes to the supervisor afterwards.
>
> I would create the connection in a connection object/process of some
> sort and that process/object would be responsible for calling
> supervisor:start_child(ChannelSup, [Connection]), when I needed a new
> channel on that connection.
>
> Roughly something like:
>
> <code>
>
> {ok, Connection} = connection:create(Host, Port, ...), % this would
> create and return an SSH connection, a gen_server would do or
> something.
>
> {ok, ChanSup} = supervisor:start_link({local, chan_sup},  
> chan_sup_callback, []),
>
> {ok, Chan1} = supervisor:start_child(ChanSup, [Connection]),
> {ok, Chan2} = supervisor:start_child(ChanSup, [Connection]),
> ...
>
> </code>
>
> Ofcourse ChanSup is a simple_one_for_one supervisor with an init/1  like:
>
> <code>
>
> init([]) ->
>       {ok, {
>                {simple_one_for_one, 10, 10},
>                [{channel,{channel, start_link, []},
>                    transient, 5000, worker, [channel]}]}}.
>
> </code>
>
> I would also setup monitors b/w the Connection and the Channels, so if
> the connection dies, say if its closed, the channels would all die
> along with it. The connection's supervisor would be responsible for
> bringing up this entire tree after disaster has struck.
>
>>
>> I have to think this kind of complex startup happens frequently enough  
>> that
>> best practices have been established.  Or perhaps these situations are
>> actually rare?
>
> Dunno ;)
>
>>
>> BTW, my gut feeling is that I should leave supervisor init() alone and  
>> have
>> a worker perform complex startup.
>
> I don't really do much in my supervisor inits, sometimes in my top
> level supervisors, I read config files, etc, but that's about it. Not
> much more. That's me though... others more experienced than me may
> have different ways of using supervisor:init/1
>
> cheers,
> Essien
>>
>> Thanks,
>> Dan.
>>
>
> ________________________________________________________________
> erlang-questions (at) erlang.org mailing list.
> See http://www.erlang.org/faq.html
> To unsubscribe; mailto:
>


-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/


More information about the erlang-questions mailing list