I'm very new on elixir/phoenix. I'm working on an previously created app that have multiples repositories and today I see an example that makes me wonder what means that configuration
I think I dont know how to search that is the reason I can't find the right answer on documentation
first the app I'm working have something like
defmodule RestApi do
use Application
def start(_type, _args) do
import Supervisor.Spec, warn: false
children = [
supervisor(RestApi.Endpoint, []),
supervisor(RestApi.Repo, []),]),
supervisor(RestApi.OtherRepo, []),]),
]
opts = [strategy: :one_for_one, name: RestApi.Supervisor]
Supervisor.start_link(children, opts)
end
def config_change(changed, _new, removed) do
RestApi.Endpoint.config_change(changed, removed)
:ok
end
end
they use the function Supervisor.Spec.supervisor/3 to start/manage everything
later I found an example
defmodule RestApi do
use Application
def start(_type, _args) do
import Supervisor.Spec, warn: false
children = [
supervisor(RestApi.Endpoint, []),
worker(RestApi.Repo, []),
]
opts = [strategy: :one_for_one, name: RestApi.Supervisor]
Supervisor.start_link(children, opts)
end
def config_change(changed, _new, removed) do
RestApi.Endpoint.config_change(changed, removed)
:ok
end
end
in the example they use Supervisor.Spec.worker/3 to start/manage the repo
Think of supervisor being a branch in the supervision tree, while the worker is a leaf.
Each supervisor
is a worker
, while not each worker
is a supervisor
. Although the supervisor
has a bunch of functions specifically dedicated to manage children processes, it in fact has very low impact on productivity compared against generic gen_server
. This excerpt from OTP design principles explains what supervisor
is supposed to be for:
A supervisor is responsible for starting, stopping, and monitoring its child processes. The basic idea of a supervisor is that it is to keep its child processes alive by restarting them when necessary.
Which child processes to start and monitor is specified by a list of child specifications. The child processes are started in the order specified by this list, and terminated in the reversed order.
Besides that it is “the worker
.”
That said, there is a rule of thumb that is easy to adopt: when the process manages children processes, it’s a supervisor
, it is a worker
otherwise.
In the mentioned example:
children = [
supervisor(RestApi.Endpoint, []),
worker(RestApi.Repo, []),
]
RestApi.Endpoint
manages children processes, and RestApi.Repo
does not. Besides that, both are plain old good gen_server
s.
You use supervisor
to start processes which are Supervisors, and worker
to start workers (basically anything which is not a supervisor). You can find more on this in the Supervisor and Supervisor.Spec module docs.
It appears either the process type changed between versions, or one of those examples has a bug, but I believe it's supposed to be a worker process, but I would check the Ecto docs.
As for how it affects the application, there is no meaningful difference other than documentation of the type of process the child is - it is in fact optional in Erlang. Supervisors manage their own set of child processes, forming a tree of supervisors. You use this to isolate the effects of crashes to sub branches of that tree so that unrelated portions of the application can continue to function while the faulted branch is restarted by its supervisor. This is the source of fault tolerance in the language and is a fundamental building block of OTP.
Workers are by far the most common type of process, they do not manage child processes, and are designed to crash and be restarted by their supervisor when things go wrong, the idea being to start over from a clean, known state. Too many failures cause the parent supervisor to crash, which in turn is restarted by its supervisor - if this bubbles up to the top level supervisor of your application, the application will crash.
Hopefully that helps :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With