[erlang-questions] non-trivial supervisor idioms?
Edmond Begumisa
ebegumisa@REDACTED
Mon Sep 27 19:26:35 CEST 2010
Oops, that code should have been...
-module(chan_sup).
...
new_child(Connection) ->
supervisor:start_child(?MODULE, [Connection]).
...
Or something like that.
- Edmond -
On Tue, 28 Sep 2010 03:12:33 +1000, Edmond Begumisa
<ebegumisa@REDACTED> wrote:
> 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 <essiene@REDACTED>
> 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:erlang-questions-unsubscribe@REDACTED
>>
>
>
--
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
More information about the erlang-questions
mailing list