How to communication between children of Supervisor?

I want to emulate an order management system.
I created a supervisor that has order provider and factory as children.

defmodule MyApp.Supervisor do
  use Supervisor

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

  @impl true
  def init(_args) do
    children = [
      MyApp.OrderProvider,
      MyApp.Factory
    ]

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

Order provider need to send orders to factory.
So I made order provider just send orders by the name of factory module.

defmodule MyApp.OrderProvider do
  use GenServer

  ...

  def handle_info({:order_created, order}, state) do
    send(MyApp.Factory, {:new_order, order}

    {:noreply, state}
  end
end

But I realized that I can’t test that message is received by factory well.
I can test it if the pid of factory is injected to order provider. Then I can inject pid of test

defmodule MyApp.OrderProvider do
  use GenServer

  ...

  def handle_info({:factory_pid, factory_pid}, state) do
    {:noreply, state |> Map.put(:factory_pid, factory_pid)}
  end

  def handle_info({:order_created, order}, %{factory_pid: factory_pid} = state) do
    send(factory_pid, {:new_order, order}

    {:noreply, state}
  end
end

defmodule MyApp.OrderProviderTest do
  use ExUnit.Case

  test "" do
    send(MyApp.OrderProvider, {:factory_pid, self()}

    ...

    assert_receive {:new_order, order}
  end
end

I have no idea how to inject pid of factory to order provider because factory also should not send message to order provider by its name.

Thanks :slight_smile:

You should use Registry

2 Likes

Using pids is not a good idea because they can change in the long run… suppose the process is restarted. You would have to update all references. You use pids when monitoring, or linking processes. But do not use them to locate a worker.

Factory pattern? Why a process for this? A simple function should do the trick.

Do not use processes to model object, use Struct, or Ecto schema.

You might read to spawn or not to spawn.

2 Likes

Also relevant, in the docs: