How to add a child process in my application.ex?

I have a phoenix where I’m working on Redix. So what I did to start this I added one more child and in the supervisor.

defmodule Gorm.Application do
  # See https://hexdocs.pm/elixir/Application.html
  # for more information on OTP Applications
  @moduledoc false

  use Application

  def start(_type, _args) do
    # List all child processes to be supervised
    children = [
      # Start the Ecto repository
      Gorm.Repo,
      # Start the endpoint when the application starts
      GormWeb.Endpoint,
      # Starts a worker by calling: Gorm.Worker.start_link(arg)
      # {Gorm.Worker, arg},
      Gorm.RedisPool
    ]

    # See https://hexdocs.pm/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: Gorm.Supervisor]
    Supervisor.start_link(children, opts)
  end

  # Tell Phoenix to update the endpoint configuration
  # whenever the application is updated.
  def config_change(changed, _new, removed) do
    GormWeb.Endpoint.config_change(changed, removed)
    :ok
  end
end

And here is my redis_pool.ex file

defmodule Gorm.RedisPool do
  use Supervisor

  @redis_connection_params host: Application.get_env(:gorm, :redis_host),
                           password: Application.get_env(:gorm, :redis_password),
                           port: Application.get_env(:gorm, :redis_port),
                           database: Application.get_env(:gorm, :redis_database)

  def start_link() do
    GenServer.start_link(__MODULE__, [])
  end

  def init([]) do
    pool_opts = [
      name: {:local, :redix_poolboy},
      worker_module: Redix,
      size: 10,
      max_overflow: 5,
    ]

    children = [
      :poolboy.child_spec(:redix_poolboy, pool_opts, @redis_connection_params)
    ]

    supervise(children, strategy: :one_for_one, name: __MODULE__)
  end

  def command(command) do
    :poolboy.transaction(:redix_poolboy, &Redix.command(&1, command))
  end

  def pipeline(commands) do
    :poolboy.transaction(:redix_poolboy, &Redix.pipeline(&1, commands))
  end
end

So when I try to run my server it’s giving me this error

Compiling 16 files (.ex)
Generated gorm app
[info] Running GormWeb.Endpoint with cowboy 2.7.0 at 0.0.0.0:4000 (http)
[info] Access GormWeb.Endpoint at http://localhost:4000
[info] Application gorm exited: Gorm.Application.start(:normal, []) returned an error: shutdown: failed to start child: Gorm.RedisPool
    ** (EXIT) an exception was raised:
        ** (UndefinedFunctionError) function Gorm.RedisPool.start_link/1 is undefined or private
            (gorm) Gorm.RedisPool.start_link([])
            (stdlib) supervisor.erl:379: :supervisor.do_start_child_i/3
            (stdlib) supervisor.erl:365: :supervisor.do_start_child/2
            (stdlib) supervisor.erl:349: anonymous fn/3 in :supervisor.start_children/2
            (stdlib) supervisor.erl:1157: :supervisor.children_map/4
            (stdlib) supervisor.erl:315: :supervisor.init_children/2
            (stdlib) gen_server.erl:374: :gen_server.init_it/2
            (stdlib) gen_server.erl:342: :gen_server.init_it/6
            (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
** (Mix) Could not start application gorm: Gorm.Application.start(:normal, []) returned an error: shutdown: failed to start child: Gorm.RedisPool
    ** (EXIT) an exception was raised:
        ** (UndefinedFunctionError) function Gorm.RedisPool.start_link/1 is undefined or private
            (gorm) Gorm.RedisPool.start_link([])
            (stdlib) supervisor.erl:379: :supervisor.do_start_child_i/3
            (stdlib) supervisor.erl:365: :supervisor.do_start_child/2
            (stdlib) supervisor.erl:349: anonymous fn/3 in :supervisor.start_children/2
            (stdlib) supervisor.erl:1157: :supervisor.children_map/4
            (stdlib) supervisor.erl:315: :supervisor.init_children/2
            (stdlib) gen_server.erl:374: :gen_server.init_it/2
            (stdlib) gen_server.erl:342: :gen_server.init_it/6
            (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3

Can anyone help me here?

Hi , You have to give startlink/1 something like that,

def start_link(args) do
    GenServer.start_link(__MODULE__, args)
  end

inside children you have to pass, empty value

{Gorm.RedisPool, []}
1 Like

Now this one is giving me error.

What is the error? Consider that it should be __MODULE__, not MODULE

It is MODULE. I think it’s not showing here

Try with,

Supervisor.init(children, strategy: :one_for_one, name: __MODULE__)
Compilation error in file lib/gorm/redis_pool.ex ==
** (CompileError) lib/gorm/redis_pool.ex:25: undefined function supervise/2
    (elixir) src/elixir_locals.erl:98: :elixir_locals."-ensure_no_undefined_local/3-lc$^0/1-0-"/2
    (elixir) src/elixir_locals.erl:99: anonymous fn/3 in :elixir_locals.ensure_no_undefined_local/3
    (stdlib) erl_eval.erl:680: :erl_eval.do_apply/6
    (elixir) lib/kernel/parallel_compiler.ex:229: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7

It’s giving me this error

This forum uses markdown to format the posts, thats why __MODULE__ turns into MODULE.

You can use backticks to annotate inline code segments: `__MODULE__`.

Also please tell us what your new error is. And how your code looks like that produces the current error.

I tried this it’s giving me same error which you saw above.

Supervisor.Spec.supervise/2 is deprecated API, please use Supervisor.start_link/2 instead, as it was used in your Gorm.Application module.

1 Like

Like this?

defmodule Gorm.RedisPool do
  use Supervisor

  @redis_connection_params host: Application.get_env(:gorm, :redis_host),
                           password: Application.get_env(:gorm, :redis_password),
                           port: Application.get_env(:gorm, :redis_port),
                           database: Application.get_env(:gorm, :redis_database)

  def start_link() do
    Supervisor.start_link(__MODULE__, [])
  end

  def init([]) do
    pool_opts = [
      name: {:local, :redix_poolboy},
      worker_module: Redix,
      size: 10,
      max_overflow: 5,
    ]

    children = [
      :poolboy.child_spec(:redix_poolboy, pool_opts, @redis_connection_params)
    ]

    Supervisor.init(children, strategy: :one_for_one, name: __MODULE__)
  end

  def command(command) do
    :poolboy.transaction(:redix_poolboy, &Redix.command(&1, command))
  end

  def pipeline(commands) do
    :poolboy.transaction(:redix_poolboy, &Redix.pipeline(&1, commands))
  end
end

Replace Supervisor.init(children, strategy: :one_for_one, name: __MODULE__) with Supervisor.start_link(children, strategy: :one_for_one, name: __MODULE__), like @NobbZ noted.

Yes I did that. But it’s still giving me the same error

Which error?

This one


Compiling 1 file (.ex)
[info] Running GormWeb.Endpoint with cowboy 2.7.0 at 0.0.0.0:4000 (http)
[info] Access GormWeb.Endpoint at http://localhost:4000
[info] Application gorm exited: Gorm.Application.start(:normal, []) returned an error: shutdown: failed to start child: Gorm.RedisPool
    ** (EXIT) an exception was raised:
        ** (UndefinedFunctionError) function Gorm.RedisPool.start_link/1 is undefined or private
            (gorm) Gorm.RedisPool.start_link([])
            (stdlib) supervisor.erl:379: :supervisor.do_start_child_i/3
            (stdlib) supervisor.erl:365: :supervisor.do_start_child/2
            (stdlib) supervisor.erl:349: anonymous fn/3 in :supervisor.start_children/2
            (stdlib) supervisor.erl:1157: :supervisor.children_map/4
            (stdlib) supervisor.erl:315: :supervisor.init_children/2
            (stdlib) gen_server.erl:374: :gen_server.init_it/2
            (stdlib) gen_server.erl:342: :gen_server.init_it/6
            (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
** (Mix) Could not start application gorm: Gorm.Application.start(:normal, []) returned an error: shutdown: failed to start child: Gorm.RedisPool
    ** (EXIT) an exception was raised:
        ** (UndefinedFunctionError) function Gorm.RedisPool.start_link/1 is undefined or private
            (gorm) Gorm.RedisPool.start_link([])
            (stdlib) supervisor.erl:379: :supervisor.do_start_child_i/3
            (stdlib) supervisor.erl:365: :supervisor.do_start_child/2
            (stdlib) supervisor.erl:349: anonymous fn/3 in :supervisor.start_children/2
            (stdlib) supervisor.erl:1157: :supervisor.children_map/4
            (stdlib) supervisor.erl:315: :supervisor.init_children/2
            (stdlib) gen_server.erl:374: :gen_server.init_it/2
            (stdlib) gen_server.erl:342: :gen_server.init_it/6
            (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3

For this, you probably have to apply what @GokulSubramaniam wrote.

In general, UndefinedFunctionError) function Gorm.RedisPool.start_link/1 is undefined or private means that the Gorm.RedisPool module does not define a public function named start_link and taking 1 argument (that’s the meaning of the /1). The problem is one of these:

  • Function start_link is simply not defined at all
  • Function start_link is defined, but it takes a different number of arguments (like zero or more than one)
  • Function start_link is defined, but private

Seeing the code that you posted at the beginning, you are probably on the second case.

So why did you revert the change from How to add a child process in my application.ex??

Too many answers are here :sweat_smile: Got confused

defmodule Gorm.RedisPool do
  use Supervisor

  @redis_connection_params host: Application.get_env(:gorm, :redis_host),
                           password: Application.get_env(:gorm, :redis_password),
                           port: Application.get_env(:gorm, :redis_port),
                           database: Application.get_env(:gorm, :redis_database)

  def start_link() do
    Supervisor.start_link(__MODULE__, [])
  end

  def init([]) do
    pool_opts = [
      name: {:local, :redix_poolboy},
      worker_module: Redix,
      size: 10,
      max_overflow: 5,
    ]

    children = [
      :poolboy.child_spec(:redix_poolboy, pool_opts, @redis_connection_params)
    ]

    Supervisor.init(children, strategy: :one_for_one, name: __MODULE__)
  end

  def command(command) do
    :poolboy.transaction(:redix_poolboy, &Redix.command(&1, command))
  end

  def pipeline(commands) do
    :poolboy.transaction(:redix_poolboy, &Redix.pipeline(&1, commands))
  end
end

I did that which @GokulSubramaniam told here in my application file

defmodule Gorm.Application do
  # See https://hexdocs.pm/elixir/Application.html
  # for more information on OTP Applications
  @moduledoc false

  use Application

  def start(_type, _args) do
    # List all child processes to be supervised
    children = [
      # Start the Ecto repository
      Gorm.Repo,
      # Start the endpoint when the application starts
      GormWeb.Endpoint,
      # Starts a worker by calling: Gorm.Worker.start_link(arg)
      # {Gorm.Worker, arg},
      {Gorm.RedisPool, []}
    ]

    # See https://hexdocs.pm/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: Gorm.Supervisor]
    Supervisor.start_link(children, opts)
  end

  # Tell Phoenix to update the endpoint configuration
  # whenever the application is updated.
  def config_change(changed, _new, removed) do
    GormWeb.Endpoint.config_change(changed, removed)
    :ok
  end
end

This line in RedisPool is still wrong, it should be Supervisor.start_link(children, strategy: :one_for_one, name: __MODULE__)

The start_link function is how you start (and link) an OTP process, while init is a callback: you normally do not call it directly, it is called by start_link internally to initialize the process.

EDIT: sorry, I am mistaken and I probably confused you, it’s good as you did in the last post: you are calling Supervisor.init inside your own definition of init, which is fine