[erlang-questions] preserving state through a gen_server restart

James Aimonetti <>
Sat Oct 20 07:59:34 CEST 2012


On Sat, 20 Oct 2012 00:04:31 -0400
Siraaj Khandkar <> wrote:

> On Oct 19, 2012, at 11:03 AM, Ivan Uemlianin wrote:
> 
> > Dear All
> > 
> > I have an erlang/OTP application consisting mostly of gen_servers.  One
> > repeated pattern is having a gateway/aggregate gen_server process that
> > provides access (and other management) to individual gen_server processes,
> > e.g.:
> > 
> >              my_sup
> >                 |
> >              my_lambs
> >             /        \      \
> >        my_lamb     my_lamb    my_lamb    ...

In the interest of a non-ETS idea, perhaps consider changing your hierarchy to
something like this:

         my_sup
       /        \
my_lambs_sup   my_lambs_srv
  /       \        
my_lamb  my_lamb

I don't know how the name->pid mapping occurs, but assuming the my_lamb process
knows its name (as part of its state) you can do a couple things, I think.

1) In my_lambs_sup, have a start_lamb function that, after starting the my_lamb
process, sends the pid() to my_lambs_srv:add_lamb.

2) When my_lambs:add_lamb is called, ask the my_lamb process for its name
(again, assuming it knows its name), and do a gen_server:cast(Srv, {add_lamb,
Pid, Name}) to update the dict.

3) Should the my_lambs process die, you could do something like this in init/1:

init([]) ->
  ... do stuff ...
  [my_lambs_srv:add_lamb(P)
   || {_,P,_,_} <- supervisor:which_children(my_lambs_sup)
  ],

  ... do other stuff
  {ok, #state{}}.

Since add_lamb/1 is a cast, you won't have a weird deadlock in the gen_server's
init. As long as you structure your my_sup to start the my_lambs_sup supervisor
first, it will be able to respond to the which_children/1 call as well. Should
allow you to rebuild the state fairly quickly and accurately on restart of the
my_lambs_srv process (and should work on clean start too).

Anyway, rudimentary attempt here but might be useful or instructive?

> > 
> > my_lambs' state variable holds a dictionary {LambName: LambPid} and among
> > other functions it allows me to call lambs by name instead of my Pid.
> > 
> > If my_lambs terminates normally --- e.g., if the whole application is
> > closing down --- its terminate/s function can call my:lamb:stop for each of
> > the processes in its care.
> > 
> > However, if my_lambs terminates abnormally, and is restarted by my_sup, I
> > think I'd like to preserve its state variable --- at least the Pids of the
> > my_lamb processes --- so that it can be passed on to the new version of
> > my_lambs.
> > 
> > I'd like to avoid losing all of the my_lamb processes, if the my_lambs
> > process crashes.
> > 
> > Can state be passed to the supervisor, to be used when it restarts its
> > child?
> > 
> > Could I park the state variable in some kind of holding process, so that
> > the new my_lambs can retrieve it?
> > 
> > Or is there another way of doing this?
> 
> 
> Seems like ETS is the natural choice for this sort of thing.
> 
> 



-- 
James Aimonetti
Distributed Systems Engineer / DJ MC_

2600hz | http://2600hz.com
sip:
tel: 415.886.7905
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20121019/83a89f2d/attachment.bin>


More information about the erlang-questions mailing list