Checking for existing child in OTP simple_on_for_one supervisor
I'm writing an map/reduce word counter to learn OTP. I've created a simp开发者_StackOverflowle_one_for_one supervisor that can start reducers. For every Key, I would like a to check if there is already a child, if not, let the supervisor create the child.
I currently start childs in the supervisor module like this:
start_child(Key) ->
supervisor:start_child(?SERVER, [Key]).
I would like to do something like this (untested):
start_child(Key) ->
case supervisor:child_pid(Key) of
Pid -> Pid;
_ -> supervisor:start_child(?SERVER, [Key])
end.
What is a good OTP way to find out if there is already a child for Key?
Build a supervisor that starts:
- A gen_server. Let's call it
reducer_server
- A simple_one_for_one supervisor. Let's call it
reducer_sup
Make sure your main supervisor starts reducer_sup
before reducer_server
. The state of reducer_server
could be a dictionary of Key -> Pid pairs. reducer_server
would then have a function like reduce(Key)
which either finds the key in the dictionary and knows the corresponding process, or doesn't find the key and runs a function like:
new_reduce(Key) ->
case supervisor:start_child(reducer_sup, [Key]) of
{ok, Pid} when is_pid(Pid) -> {ok, Pid};
{ok, Pid, _} when is_pid(Pid) -> {ok, Pid};
_ -> error
end.
Just add the resulting pid to your state and you should be ready for the next call to reduce/1
. I'd recommend reading this and this to get a better feel for how all of these parts work together. If you were putting this code into a production environment, you may want to consider things like:
- What happens when processes die? Hint: check for liveness with
is_process_alive/1
. - What happens if either
reducer_server
orreducer_sup
dies?
精彩评论