kasperkronborg

kasperkronborg

Supervisor without any children

I was looking over the source code for plug_cowboy and saw that in the Plug.Cowboy.start/2 they return a supervisor without any children Supervisor.start_link([], strategy: :one_for_one). What’s the reasoning for doing that?

I’m somewhat new to Elixir, so really interested in learning.

Thanks!

Marked As Solved

msimonborg

msimonborg

After looking at the source code this is my impression, I could be off on some or all aspects but I think this is generally correct.

Plug.Cowboy provides Plug.Cowboy.child_spec/1. When you add Plug.Cowboy to your supervision tree it starts a listener. Here’s some informative documentation and example from the library, found in lib/plug/cowboy/drainer.ex

defmodule Plug.Cowboy.Drainer do
  @moduledoc """
  Process to drain cowboy connections at shutdown.

  When starting `Plug.Cowboy` in a supervision tree, it will create a listener that receives
  requests and creates a connection process to handle that request. During shutdown, a
  `Plug.Cowboy` process will immediately exit, closing the listener and any open connections
  that are still being served. However, in most cases, it is desirable to allow connections
  to complete before shutting down.

  This module provides a process that during shutdown will close listeners and wait
  for connections to complete. It should be placed after other supervised processes that
  handle cowboy connections.

  ...

  ## Examples
      # In your application
      def start(_type, _args) do
        children = [
          {Plug.Cowboy, scheme: :http, plug: MyApp, options: [port: 4040]},
          {Plug.Cowboy, scheme: :https, plug: MyApp, options: [port: 4041]},
          {Plug.Cowboy.Drainer, refs: [MyApp.HTTP, MyApp.HTTPS]}
        ]
        opts = [strategy: :one_for_one, name: MyApp.Supervisor]
        Supervisor.start_link(children, opts)
      end
  """

This seems to cover all or most of the supervision and process generation that Plug.Cowboy provides, which happens inside your own app’s supervision tree (in most cases through Phoenix.Endpoint, probably). It doesn’t explain Plug.Cowboy’s childless supervisor. If we look at the Plug.Cowboy.start/2 callback where the supervisor is defined:

  require Logger

  @doc false
  def start(_type, _args) do
    Logger.add_translator({Plug.Cowboy.Translator, :translate})
    Supervisor.start_link([], strategy: :one_for_one)
  end

Plug.Cowboy is using the start callback to hook into the application lifecycle and add functionality to Logger. From what I can see, this is the sole reason for starting the Plug.Cowboy application. The Supervisor satisfies the application behaviour’s expected return values from start/2.

I scanned the source files (there are only 5 and they’re mostly short, thankfully :slightly_smiling_face: ) and didn’t see a reference to starting processes under this supervisor. It doesn’t have any name registration either, which would make that unnecessarily hard to achieve.

Also Liked

hauleth

hauleth

Not really. You can add children dynamically to “regular” supervisors as well. The thing is that if you add them to “regular” one it is assumed that these will live forever rather than being temporary.

josevalim

josevalim

Creator of Elixir

This is correct. Great spelunking @msimonborg!

kasperkronborg

kasperkronborg

Thank you for your thorough explanation.

I also went looking through the source code and didn’t seem to find indications of children ever being added to the supervisor.

So what you are saying is that it’s just there to fulfill the expected return of the start/2 callback?

msimonborg

msimonborg

Actually it was LiveView where I last saw something similar. The TODO comment makes it explicit about the intent

hauleth

hauleth

My comment was just about the fact that you do not need DynamicSupervisor for dynamic children list. I think that @msimonborg has the correct answer why the supervisor is started with empty children list, it is just for the configuration, not runtime stuff.

Where Next?

Popular in Questions Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
Codball
Mix format works fine if run from the cmd. I’ve followed this to facilitate the implementation into VSC which involves downloading an ext...
New
wernerlaude
In AR this is so simple @articles = current_user.articles How to do in Ecto? def index(conn, _params) do current_user = conn.assig...
New

Other popular topics Top

JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
AstonJ
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New

We're in Beta

About us Mission Statement