Checkout my post on the Erlware blog about using a simple one for one to handle DB requests from webmachine for a better tutorial.
I found the posts online about Erlang’s simple_one_for_one supervisors pretty lacking so I thought I’d throw something together about how I use them.
Using Nitrogen I have a chat site that communicates with an ejabberd backend. Each user gets a user_server process (a gen_server) that handles all the communication with ejabberd through the exmpp library from Process One. These are dynamic servers so they are unnamed and use simple_one_for_one supervisors for their supervision, which sit under the main applications supervisor.
The user_simple_one_for_one.erl looks basically like this:
start_link() ->
supervisor:start_link(?MODULE, []).
init([]) ->
UserSpec = {user_server, {user_server, start_link, []},
temporary, 2000, worker, [user_server]},
StartSpecs = {{simple_one_for_one, 0, 1}, [UserSpec]},
{ok, StartSpecs}.
Unlike a normal supervisor no child process is started after calling user_simple_one_for_one:start_link(). 0 and 1 define the number of restarts in 1 second and we use temporary for the worker since users come and go. Thus the server should shutdown on normal exit and not restart. It order to start this child we call user_server:start(Pid). So in user_server.erl we need both start_link/2 and start/3.
start_link(UserName, Password) -> gen_server:start_link(?MODULE, [UserName, Password], []). start(Super, UserName, Password) -> supervisor:start_child (Super, [UserName, Password]).
We then need to start the supervisor somewhere and store its Pid to be passed into a function that passes the supervisors Pid to the user_server for it to use to call start_child:
{ok, Pid} = user_simple_one_for_one:start_link().
jabber_login (Sup, UserName, Password) -> user_server:start(Sup, UserName, Password).
Now we have dynamic supervision of a dynamic gen_server.
thanks,
very useful. Before I can understand simple_one_for_one supervisor.