How to structure an Erlang OTP UDP server
erlang, erlang-otp, udp
Solution
The key answer to this question is: "how do you want your application to crash?"
If a worker dies, then what should happen? If this should stop everything, including the UDP connection, then surely you can just spawn_link them under the my_server directly, no supervisor tree needed. But if you want them to be able to gracefully restart or something else, then the above diagram is usually better. Perhaps add a monitor on the workers from my_server so it can keep a book of who is alive.
In my utp erlang library, I have almost the same construction. A master handles the UDP socket and forwards to workers based on a routing table kept in ETS. Each worker keeps a connection state and can handle the incoming information.
Since you don't track state, then your best bet is probably to run via `proc_lib:spawn_link` and then hook them to the s_1_1 supervisor as transient processes. That way, you will force too many crashes to be propagated up the supervisor tree but allow them to exit with `normal`. This allows you to have them run exactly once.
Note that you could also handle everything directly in the my_server, but then you will not be able to process data concurrently. This may or may not be acceptable. The general rule is to spawn a new process when you have concurrent work that needs to be executed next to each other, blocks or otherwise behaves in some way.
Problem
I am just reading Manning's Erlang & OTP In Action. Very good book, I think. It contains a nice TCP server example but I'd like to write a UDP server. This is how I structured my app so far. ``` my_app % app behaviour |-- my_sup % root supervisor |-- my_server.erl % gen_server to open UDP connection and dispatch |-- my_worker_sup % simple_one_to_one supervisor to start workers |-- my_worker_server % gen_server worker ``` So, `my_app` starts `my_sup`, which in turn starts `my_worker_sup` and `my_server`. The UDP connection is opened in `my_server` in active mode such that `handle_info/2` is invoked on each new UDP message in response to which I call `my_worker_sup:start_child/2` to pass the message to a new worker process for processing. (The last call to `start_child/2` is in fact, as per the book's recommendation, wrapped in an API function to hide some of the details, but this is essentially what happens.) Am I suffering from OTP fever? Should the `my_worker_server` really implement the gen_server behaviour? Do I need `my_worker_sup` at all? I set it up in like this so that I can use `my_worker_sup` as a factory via the `start_child/2` call but I only use the worker's `init/1` and `handle_info(timeout,State)` functions to first setup state and then to process the message before shutting the worker down. Should I just spawn the worker directly? Is another behaviour better suited, perhaps? Thanks, HC