3

I have this code:

defmodule MyApp.JobRunner do
  use DynamicSupervisor
  alias MyApp.MyWorker

  def start_link(_arg) do
    DynamicSupervisor.start_link(__MODULE__, :ok, name: __MODULE__)
  end

  def init(:ok) do
    IO.puts("MyApp.JobRunner: init")
    DynamicSupervisor.init(strategy: :one_for_one)
  end

  def add_new_task(my_task_id) do
    child_spec = {MyWorker, {my_task_id}}
    IO.puts("MyApp.JobRunner: child_spec > #{Kernel.inspect(child_spec)}")

    res = DynamicSupervisor.start_child(__MODULE__, child_spec)
    IO.puts("MyApp.JobRunner: add_new_task > #{Kernel.inspect(res)}")
    res
  end

Each time I'll call add_new_task(my_task_id) with a new argument, it'll return an error

{:error, {{:badmatch, {:error, {:already_started, #PID<0.550.0>}}},

What's the matter? How is it "already started" if it's called a new argument each time?


MyApp.MyWorker is a GenServer. Can this error have to do with the way it's implemented in my project? I can provide the code

Koklushkin
  • 155
  • 7

1 Answers1

0

In MyWorker.start_link do you have something like GenServer.start_link(__MODULE__, init_arg, name: __MODULE__)? If so you'll only be able to start one child because the __MODULE__ macro gets replaced by MyWorker and there can only be one process with that name.

You need a new name for each child. Since you initial state you are passing in is {my_task_id} use that as the name:

  defmodule MyWorker do
    def start_link({name}) do
      GenServer.start_link(__MODULE__, initial, name: name)
    end
  end
Gangstead
  • 4,152
  • 22
  • 35
  • `{name}` is incorrect. Not? – Koklushkin May 03 '23 at 12:55
  • In your child spec it looks like you are passing the tuple `{my_task_id}` so that's what will be passed into `MyWorker.start_link`. There are a couple ways to do it mentioned here: https://hexdocs.pm/elixir/1.14.3/DynamicSupervisor.html#module-migrating-from-supervisor-s-simple_one_for_one . In my app I used the form `spec = %{id: MyWorker, start: {MyWorker, :start_link, [foo, bar, baz]}}` and `[foo, bar, baz]` is what gets passed into the `MyWorker.start_link` – Gangstead May 03 '23 at 14:28