gouthamvel

gouthamvel

:poolboy doesn't play nice with Task.async. Help

I’m fairly new to elixir. Here’s the code:

defmodule MovAvi.Pool.Executor do
  defmodule Worker do
    use GenServer

    def start_link(args) do
      GenServer.start_link(__MODULE__, args, [])
    end

    def init(args \\ []) do
      uniq_id = :rand.uniform(500)
      IO.puts("Starting worker with uniq_id: #{uniq_id}")
      {:ok, {uniq_id}}
    end

    def worker_called(server, args) do
      GenServer.call(server, {:worker_called, args})
    end

    def handle_call({:worker_called, args}, _from, state) do
      IO.puts("worker_called #{args} #{inspect(state)}")
      :timer.sleep(500)
      {:reply, nil, state}
    end
  end

  use GenServer

  def start_link(args) do
    GenServer.start_link(__MODULE__, args, name: __MODULE__)
  end

  def init(args \\ [pool_size: 2, pool_overflow: 0]) do
    {:ok, pool} =
      :poolboy.start_link(
        worker_module: args[:worker_module],
        size: args[:pool_size],
        max_overflow: args[:pool_overflow]
      )

    {:ok, pool}
  end

  def wait_for_tasks(tasks) do
    GenServer.call(__MODULE__, {:wait_for_tasks, tasks})
  end

  def run_with_task(id) do
    GenServer.call(__MODULE__, {:run_with_task, id})
  end

  def run(id) do
    GenServer.call(__MODULE__, {:run, id})
  end

  def handle_call({:wait_for_tasks, tasks}, _from, state) do
    tasks |> Enum.each(&Task.await(&1))
    {:reply, nil, state}
  end

  def handle_call({:run_with_task, id}, _from, pool) do
    task =
      Task.async(fn ->
        :poolboy.transaction(pool, fn worker ->
          Worker.worker_called(worker, id)
        end)
      end)

    {:reply, task, pool}
  end

  def handle_call({:run, id}, _from, pool) do
    :poolboy.transaction(pool, fn worker ->
      Worker.worker_called(worker, id)
    end)

    {:reply, nil, pool}
  end
end

{:ok, executer} =
  MovAvi.Pool.Executor.start_link(worker_module: MovAvi.Pool.Executor.Worker, pool_size: 2)

Enum.map(0..5, fn id ->
  MovAvi.Pool.Executor.run(id)
end)

IO.puts("=== running run_with_task ===")

Enum.map(6..10, fn id ->
  MovAvi.Pool.Executor.run_with_task(id)
end)
|> MovAvi.Pool.Executor.wait_for_tasks()

I’m playing around with :poolboy and ran into an issue. With normal run the GenServer is blocked till the worker :poolboy.transaction is completed this is expected. Also only 2 workers are created as mentioned.

But when I use run_with_task, :poolboy creates new worker for every id. I’m confused why this is happening.

I’m expecting run_with_task to create all Task and the Task should be blocked for :poolboy to allocate workers.

Any insights and help is appreciated. Also If you think there’s a better way to write the code do let me know.

Thanks

First Post!

dom

dom

Executor.init receives [worker_module: MovAvi.Pool.Executor.Worker, pool_size: 2] as args, so args[:pool_overflow] returns nil, not 0. Consider making the default arg an empty list and using a default per item instead like args[:pool_overflow] || 0.

(In fact the default arg for init will never be used, since the callback used by OTP is init/1, not init/0)

Where Next?

Popular in Questions Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
hpopp
To simplify some tasks at work, I wrote and published this package yesterday. It’s a simple macro that enables Access behaviour on struct...
New
wernerlaude
In AR this is so simple @articles = current_user.articles How to do in Ecto? def index(conn, _params) do current_user = conn.assig...
New
jc00ke
Expanding on this topic: https://forum.elixirforum.net/t/map-typespec-question/19217 Let’s say I have a map with required and optional k...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

Other popular topics Top

sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
977 41022 311
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 45766 226
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New

We're in Beta

About us Mission Statement