How run multiple worker based on dynamic supervisor

I have following DynamicSupervisor:

defmodule Vampire_supervisor do
  use DynamicSupervisor

  def start_link() do
    DynamicSupervisor.start_link(__MODULE__, :ok)
    # Supervisor.start_link(__MODULE__, {limits, low, high})
  end

  def init(:ok) do
    DynamicSupervisor.init(strategy: :one_for_one)
  end

  def start_worker(super_pid) do
    child_spec = {Vampire_finder, []}
    DynamicSupervisor.start_child(super_pid, child_spec)
  end
end

Vampire_finder is a genserver module as follows:

defmodule Vampire_finder do
  use GenServer

  ## External API
  def start_link([]) do
    GenServer.start(__MODULE__, [], name: __MODULE__)
  end

  def cal_vampire({pid, low, high}) do
    # GenServer.call(pid, :next_number)
    GenServer.cast(pid, {:set_number, low, high})
  end

  def get_vampire(pid) do
    GenServer.call(pid, :next_number)
  end

  ## GenServer Implementation
  def handle_call(:next_number, _from, all_vampire_nums) do
    #all_vampire_nums = VampireNumbers.get_vampire_nums(low, high)
    {:reply, all_vampire_nums, all_vampire_nums}
  end

  def handle_cast({:set_number, low, high}, _) do
    all_vampire_nums = VampireNumbers.get_vampire_nums(low, high)
    {:noreply, all_vampire_nums}
  end

end

When I am trying to call the supervisor using
{:ok, super_pid} = Vampire_supervisor.start_link()
IO.inspect super_pid
Vampire_supervisor.start_worker(super_pid)
Vampire_supervisor.start_worker(super_pid)

For the second startworker i am getting an error
{:error, {:already_started, #PID<0.230.0>}}

Can someone plz help?

Well, if You don’t mind I can help You in reformatting your post code by adding around ``` as markdown sign for code :slight_smile:

That is problematic with dynamic supervisor’s workers because You can have only one process per name. You should use something like Registry (local), or go for :global (distributed).

Here is an example with Registry… as You might guess, name should be unique.

  def start_link(name, args \\ %{}) do
    GenServer.start_link(__MODULE__, args, name: via_tuple(name))
  end

  defp via_tuple(name), do: {:via, Registry, {Registry.WorldWorkers, name}}

and add registry to your supervision tree

{Registry, keys: :unique, name: Registry.WorldWorkers},

You can also add this helper function to your worker.

  def whereis_name(name) do
    case Registry.lookup(Registry.WorldWorkers, name) do
      [{pid, _ref}] -> pid
      [] -> nil
    end
  end
1 Like

How to close this question as the issue is resolved?

No, problem, it is done. I made a small mistake, really appreciate your help.

You can go on a post, click on show more (…) and mark it as solution to close the topic.

Glad it helped :slight_smile: