-module(dist_super). -behaviour(supervisor). % see erl -man supervisor -export([start_link/0, init/1]). %% This is the start function for the top supervisor. %% A common pattern: implement a module that implements a %% start_link() function. I frown upon the practise of exporting %% a start() function that e.g. calls supervisor:start_link(), or %% worse: the other way around. %% start_link() -> supervisor:start_link({local,?MODULE}, ?MODULE, []). %% When the supervisor is started, it calls init(Arg). %% This function should return {ok, {SupFlags, Children}}. %% %% SupFlags : {supervision_strategy(), maxR(), maxT()} %% supervision_strategy() : one_for_one | one_for_all | simple_one_for_one %% %% Children : [ChildStartSpecification] %% ChildStartSpecification : {internal_name(), %% {module(), function(), args()}, %% shutdown_time(), %% child_type(), %% modules()} %% See erl -man supervisor for more details. %% %% A word on MaxR/MaxT: %% Choosing a good restart frequency is difficult. The following %% reasoning might help: %% %% - MaxR should be low enough that escalation is not needlessly delayed. %% Remember that if you have multiple levels of supervisors, MaxR will %% multiply; you might want to set MaxR=0 for most higher supervisors. %% - MaxT should be low enough that unrelated restarts aren't counted as %% looping restart (think: how long does it take for the effects of a %% problem to "heal"?); if MaxT is too low, there may not be time enough %% for MaxR restarts. %% %% In general, think about what should happen if a certain process restars. %% Some processes may be designed as "kernel processes", such that the only %% reasonable course of action, should they crash, is to terminate the node. %% For these processes, set MaxR of all affected supervisors to 0. %% %% I've chosen three restarts in 10 seconds. %% init(_) -> %% Let's try a novelty: %% I want to start a globally registered server, which will bring its %% name along when moving to another node. This is not as easy as it %% sounds (does it sound easy?). More explanations will follow in %% dist_server.erl, but for now, we pass along a fun that registers %% a "global reference", and one that answers the question "am I %% on the master node?" %% The global reference is a globally registered name tied to this %% supervisor, since it will not restart during the application's %% lifetime. %% RegisterF = fun() -> global:re_register_name(?MODULE, whereis(?MODULE)) end, CheckF = fun() -> case global:whereis_name(?MODULE) of Pid when node(Pid) == node() -> true; _ -> false end end, SupFlags = {one_for_one, 3, 10}, {ok, {SupFlags, [{server, {dist_server, start_link, [RegisterF, CheckF]}, permanent, 10000, worker, [dist_server]}]}}.