Elixir/Erlang and Cowboy - How to use supervisors

Charlie Source

When you use Mix to create an application, it always adds a root supervisor file to the project. Note how the 'child spec' array in the supervise function is empty.

app.ex:

defmodule App.Supervisor do
    use Supervisor

    def start_link do
        Supervisor.start_link(__MODULE__, :ok)
    end

    def init(args) do
       supervise([], [strategy: :one_for_one])
    end
end

An entry point for the application is also created for you. Working through some of the examples I found online, I wrote the following:

defmodule App do
    def start(_type, _args) do
        dispatch = :cowboy_router.compile([
            {
                :_,
                [
                    # Simple JSON test.
                    {"/test", app.Handle.test, []},
                ]
            }
        ])

        {:ok, _} = :cowboy.start_http(
            :http,
            100,
            [{:port, 8080}],
            [{ :env, [{:dispatch, dispatch}]}]
        )

        App.Supervisor.start_link()
    end
end

This application works, but it also works if I remove the call to App.Supervisor.start_link() in App.start().

So what's the supervisor for in this case? If the child spec for the supervisor is empty, then what's the point of it?

For example, in the Elixir example found here - https://github.com/IdahoEv/cowboy-elixir-example/blob/master/lib/cowboy_elixir_example.ex - You can see that the call to start the supervisor is commented out on line 65.

But in an official Cowboy Erlang example, this file - https://github.com/ninenines/cowboy/blob/master/examples/hello_world/src/hello_world_app.erl - Creates a similar root supervisor with no child spec, and then calls it in the main application file here, on line 22 - https://github.com/ninenines/cowboy/blob/master/examples/hello_world/src/hello_world_app.erl

concurrencyerlangelixirotpsupervisor

Answers

answered 2 years ago tkowal #1

There is a higher level concept than supervision tree: application.

A project usually consists of many applications. Each of them can have its own supervision tree. If you have Erlang and Elixir installed properly with wx widgets, you can see it by running:

:observer.start

This opens a graphical user interface. Go to Applications tab and click on application names on the right. It only shows processes following OTP principles. If your example is similar to those from cowboy repository, then you should see all your acceptors under ranch.

Supervisor with empty worker list does nothing. It is there, in case you need to add some processes later. It doesn't do any harm to start it, but it also isn't necessary. It might be the case, that programmers didn't bother to delete after they started project from template.

There are two kinds of applications:

  • active applications - which use processes to do their job (for example ranch), they should start and stop as a unit
  • library applications - which just provide some code, that is run in context of other processes (for example json decoders/encoders)

Usually active applications have top level supervisor and library applications don't.

comments powered by Disqus