Skip to content

Example of How to Start Children like a Regular Supervisor #268

@RodolfoSilva

Description

@RodolfoSilva

@derekkraan, is this the correct way to start workers with the application? I was wondering if there is a better approach to initiate some jobs and automatically restart these jobs if they crash.

If so, can I add this to the documentation?

application.ex

defmodule MyApp.Application do
  use Application
  def start(_type, _args) do
    children = [
      {Horde.DynamicSupervisor, [name: MyApp.DistributedSupervisor, strategy: :one_for_one]},
      MyApp.Supervisor
    ]

    Supervisor.start_link(children, strategy: :one_for_one)
  end
end

supervisor.ex

defmodule MyApp.Supervisor do
  use Supervisor
  require Logger

  def start_link(init_arg \\ []) do
    Supervisor.start_link(__MODULE__, init_arg, name: __MODULE__)
  end

  @impl true
  def init(_init_arg) do
    children =
      [
        {Task, [id: :task, args: [:infinity]]},
        {Agent, [id: :agent, args: [fn -> %{} end]]},
        {GenServer, [id: : gen_server, args: [DefinedGenServer, {500, pid}]]}
      ]

    children
    |> Enum.map(&create_child_spec/1)
    |> Supervisor.init(strategy: :one_for_one)
  end

  defp create_child_spec({worker, opts}) do
    %{
      id: worker,
      restart: :transient,
      start:
        {Task, :start_link,
         [
           fn ->
             child_spec =
               Enum.into(opts, %{
                 id: worker,
                 type: :worker,
                 restart: :transient,
                 start: {worker, :start_link, opts[:args] || []}
               })

             Logger.info("Starting worker #{inspect(worker)} over HordeSupervisor")

             Horde.DynamicSupervisor.start_child(MyApp.DistributedSupervisor, child_spec)
           end
         ]}
    }
  end

  defp create_child_spec(worker), do: create_child_spec({worker, []})
end

I've made this inspired in this test:

children = [
{Horde.DynamicSupervisor,
[
name: TestHorde,
strategy: :one_for_one,
max_restarts: 1
]},
%{
id: AddsChild,
restart: :transient,
start:
{Task, :start_link,
[
fn ->
Horde.DynamicSupervisor.start_child(TestHorde, TestChild)
end
]}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions