I have an app like
stackdelivery
├── lib
└── stackdelivery
└── application.ex
└── stackgen
└── stackgen.ex
└── supervisor.ex
stackdelivery.ex
mix.exs
application.ex is
defmodule Stackdelivery.Application do
# See http://elixir-lang.org/docs/stable/elixir/Application.html
# for more information on OTP Applications
@moduledoc false
use Application
use Supervisor
def start(_type, _args) do
import Supervisor.Spec, warn: true
# Define workers and child supervisors to be supervised
children = [
supervisor(Stackdelivery.StackGen.Supervisor, [])
]
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: Stackdelivery.StackAppSupervisor]
Supervisor.start_link(children, opts)
end
end
supervisor.ex is
defmodule Stackdelivery.StackGen.Supervisor do
@moduledoc """
Supervisor for StackGen module
"""
use Supervisor
alias Stackdelivery.Stack
def start_link do
Supervisor.start_link(__MODULE__, [], name: __MODULE__)
end
def init(_) do
IO.puts "starting StackGen.Supervisor supervisor.."
children = [
worker(Stack, [])
]
opts = [strategy: :simple_one_for_one, name: Stackdelivery.StackGenSupervisor]
supervise(children, opts)
end
def shoot, do: Supervisor.start_child(__MODULE__, [])
end
stackgen is a simple Stacn Genserver. for brevity:
defmodule Stackdelivery.Stack do
use GenServer
def init(_) do
IO.puts "Starting a New GenServer Stack"
{:ok, []}
end
....
I can’t start multiple child processes using Stackdelivery.StackGen.Supervisor.shoot
The way I am thinking is how supervision tree should be is:
Application (Main Supervisor)
└── StackGen.Supervisor (Module Supervisor)
└── Stackgen (GenServer)
Now when Application.start_link happens, how can we invoke child proceses in StackGen.Supervisor for Stackgen workers?
Supervisor.start_child/2 needs a spec! See Supervisor.Spec
Also, I think it has to have an id if you’re starting multiple GenServers of the same module.
def shoot(unique_name) do
spec = worker(Stackgen, [], [id: unique_name, restart: :transient])
Supervisor.start_child(__MODULE__, spec)
end
4 Likes
isnt transient is default for simple_one_for_one?
Is this unique name unique everytime each pid starts?
You’re right. My code doesn’t use :simple_one_for_one. The app I took the example code from uses a :one_for_one. 
I’ll play with your code and see if I can find out what’s going on.
should each time the id be unique?
In my app, I’m not using :simple_one_for_one strategy. Each GenServer I start has a unique id - that’s why the example I gave you has a unique_id argument.
can you give me an example with a code snippet?
in worker(module, args, options \\ [])
[id: module,
function: :start_link,
restart: :permanent,
shutdown: 5000,
modules: [module]]
id can be __MODULE__ right?
OK. I have a working example now. Sorry to have misled you with incorrect information. I hope this makes up for it 
Some notes:
- I think having
use Supervisor in application.ex ultimately caused the problem since they likely conflict with each other. I didn’t catch that at first.
- I forgot about this gotcha: if running from IEx, the module name is prefixed with
Elxir! (i.e. Elixir.StackDelivery.StackGen.Supervisor), so I’m not sure if that came into play or not
Nonetheless, I’ve tested this and it seems to be working fine.
application.ex
defmodule StackDelivery.Application do
@moduledoc false
use Application
def start(_type, _args) do
import Supervisor.Spec, warn: true
children = [
supervisor(StackDelivery.StackGen.Supervisor, [])
]
opts = [strategy: :one_for_one, name: StackDelivery.Supervisor]
Supervisor.start_link(children, opts)
end
end
stack_gen_supervisor.ex
defmodule StackDelivery.StackGen.Supervisor do
use Supervisor
require Logger
alias StackDelivery.StackGen
# this format is used at https://elixir-lang.org/getting-started/mix-otp/supervisor-and-application.html#simple-one-for-one-supervisors
@name StackDelivery.StackGen.Supervisor
def start_link do
Supervisor.start_link __MODULE__, [], name: @name
end
def shoot do
Supervisor.start_child(@name, [])
end
def init(_) do
Logger.info "starting StackDelivery.StackGenSupervisor"
children = [
worker(StackGen, [])
]
opts = [strategy: :simple_one_for_one, name: StackDelivery.StackGenSupervisor]
supervise(children, opts)
end
end
stack_gen.ex
defmodule StackDelivery.StackGen do
use GenServer
require Logger
def start_link(opts \\ []) do
GenServer.start_link __MODULE__, opts
end
def init(_) do
Logger.info "starting a new #{__MODULE__}"
{:ok, []}
end
end
mix.exs
defmodule StackDelivery.Mixfile do
use Mix.Project
def project do
[app: :stack_delivery,
version: "0.1.0",
elixir: "~> 1.4",
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
deps: deps()]
end
def application do
[extra_applications: [:logger],
mod: {StackDelivery.Application, []}]
end
defp deps do
[]
end
end
idk, its not working for me
iex(1)> Stackdelivery.StackGen.Supervisor.start_link
starting..module is: Stackdelivery.StackGen.Supervisor
{:ok, #PID<0.116.0>}
iex(2)> Stackdelivery.StackGen.Supervisor.start_link
works when
defmodule Stackdelivery.StackGen.Supervisor do
@moduledoc """
Supervisor for StackGen module
"""
use Supervisor
alias Stackdelivery.Stack
@name Stackdelivery.StackGen.Supervisor
def start_link do
Supervisor.start_link(__MODULE__, [])
end
wont work when Supervisor.start_link(__MODULE__, [], name: @name)