Why do I get always the same pid

Hi
I am using poolboy for managing workers.
The poolboy will spawn five workers, when the supervisor get started:

  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    # Poolboy configuration
    pool_options = [
      name: {:local, :sap_odata_service},
      worker_module: SapOdataService.Worker,
      size: 5,
      max_overflow: 5
    ]

    # Define workers and child supervisors to be supervised
    children = [
      # Starts a worker by calling: SapOdataService.Worker.start_link(arg1, arg2, arg3)
      #worker(SapOdataService.Worker, []),
      :poolboy.child_spec(:sap_odata_service, pool_options, [])
    ]

    # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: SapOdataService.Supervisor]
    Supervisor.start_link(children, opts)
  end

I am using poolboy.transaction for asking for a worker. The function that is using poolboy looks as follow:

  def get(uri, user, password) when is_binary(uri)
                               and is_binary(user)
                               and is_binary(password)
                               do
    :poolboy.transaction(:sap_odata_service, fn
                                               (pid) when is_pid(pid) ->
                                                 IO.inspect pid
                                                 GenServer.call(pid, {:get, uri, user, password})
                                             end)
  end

I wrote a test for the function above:

  test "Make requests to odata server." do

    for n <- 1..4 do
      assert {:ok, _, _, _} = Worker.get(Application.get_env(:odata_service, :url), "foo", "foo")
    end
    assert {:ok, _, _, _} = Worker.get(Application.get_env(:odata_service, :url) <> "Products(1)", "foo", "foo")

  end

As output I’ve got:

As you can see on the image, there are always the same pid.
Why do poolboy not taking different pids to process concurrently?

Thanks

You aren’t asking it to do anything concurrently. For comprehensions execute serially, so your code is checking out a worker, doing some work, checking the worker back in, then repeating. If poolboy uses a list to store its worker pids, you’re just getting the first item of the list, then putting it back on, then taking it back off.

1 Like

I rewrite the test as follow:

  test "Make requests to odata server." do

    for n <- 1..10 do
      spawn fn ->
         assert {:ok, _, _, _} = Worker.get(Application.get_env(:odata_service, :url), "foo", "foo")
      end
    end
    assert {:ok, _, _, _} = Worker.get(Application.get_env(:odata_service, :url) <> "Products(1)", "foo", "foo")

  end

And it works as expected.