I'm developing an application with 1 supervisor and several workers. Each one of those workers will just open a tcp socket, execute a listen, and then accept connections, spawning a process for each client as they arrive (I dont mind supervising these).
I'd like to make the listening addresses configurable in the application configuration, so I can have as many addresses to listen as needed (at least 1 address is needed, but any number can be specified). Each address is an ip (or hostname) and a port address. So far, nothing new.
My question is about how to declare, start, and supervise an unknown number of workers. My solution was to dynamically generate (at runtime) the result of the init/1 function in the supervisor code, like this:
-define(
CHILD(Name, Args),
{Name, {
?MODULE, start_listen, Args
}, permanent, 5000, worker, [?MODULE]
}
).
init([]) ->
{ok, Addresses} = application:get_env(listen),
Children = lists:map(
fun(Address) ->
{X1,X2,X3} = os:timestamp(),
ChildName = string:join([
"Listener-",
integer_to_list(X1),
integer_to_list(X2),
integer_to_list(X3)
], ""),
?CHILD(ChildName, [Address])
end,
Addresses
),
{ok, { {one_for_one, 5, 10}, Children }}.
This allows me to dynamically generate a name for each worker and also generate the worker definitions. So:
Is this solution acceptable? It seems to me that it's not that elegant. Is there any standard solution (or best practice, etc) for this kind of use cases?
I know about the "simple_one_for_one" strategy, that allows to dynamically add workers to a supervisor. But can it also be used to dynamically generate the worker's names? Is it better (in any way) to use "simple_one_for_one" instead of my own solution that uses "one_for_one"? (again, for this particular situation).
Thanks in advance, and sorry for the long post! :)