Poolex - A library for managing pools of workers

Hi :wave:t2:

Poolex is an Elixir library for managing pools of workers.

In short, this is a poolboy written in Elixir.

When I started this project, I had the following goals:

  • To solve the problem of missing documentation of public interfaces and “official” library usage examples.
  • To bring this library back to life. poolboy is not actively maintained. Even if poolboy is written perfectly, there may be a chance of incompatible OTP changes in the future or the appearance of new features we’d like to use.
  • Try to rewrite this library in Elixir. It’s not a problem, but I’d like to use Elixir dependencies when I’m writing in Elixir.
  • To add the ability to use different strategies for getting a worker. I think a developer may have more needs than just choosing a LIFO / FIFO. So I added the ability to describe and use implementations for operating with worker and caller process queues.

Some project links:

14 Likes

Release 0.7.0

Added FIFO implementation for getting workers from the pool. This is the same mechanism as the :fifo strategy in poolboy.

3 Likes

Release 0.8.0

Since the latest major release, many improvements have been made:

  • Shutting down the pool and its workers is more accurate.
  • The work has been optimized by eliminating unnecessary ETS tables.
  • Fixed many bugs with handling exit of workers and callers processes.
  • Added missed validation for some initialization options.

Also, there are some breaking changes. I will quote the release note for 0.8.0:

  • Option :timeout renamed to :checkout_timeout.

    • Reason: This option configures only the waiting time for worker from the pool, not the task’s work time. This naming should be more understandable on the call site.

      # Before
      Poolex.run(:my_awesome_pool, fn worker -> some_work(worker) end, timeout: 10_000)
      
      # After
      Poolex.run(:my_awesome_pool, fn worker -> some_work(worker) end, checkout_timeout: 10_000)
      
  • Poolex.run/3 returns tuple {:error, :checkout_timeout} instead of :all_workers_are_busy.

    • Reason: It is easier to understand the uniform format of the response from the function: {:ok, result} or {:error, reason}.
  • Poolex.caller() type replaced with struct defined in Poolex.Caller.t().

    • Reason: We need to save unique caller references.
  • Poolex.run!/3 was removed in favor of Poolex.run/3. The new unified function returns {:ok, result} or {:error, :checkout_timeout} and not handles runtime errors anymore.

    • Reason: We should not catch errors in the caller process. The caller process itself must choose how to handle exceptions and exit signals.

As always, here are some important links:

2 Likes

Release 0.9.0

With the last release, metrics were added to observe, analyze, and optimize the production configuration of your pools.

For now, implemented sending of pool’s size metrics: idle/busy workers count and current state “Is pool overflowed right now?”. The library starts to send these metrics via :telemetry if you pass pool_size_metrics: true on pool initialization:

children = [
  {Poolex,
    pool_id: :worker_pool,
    worker_module: SomeWorker,
    workers_count: 5,
    pool_size_metrics: true}
]

Also, I have added a plugin for PromEx library. You can check it out here.


1 Like

Nice library, thought of writing something similar in the past. Will review. Thanks for your work! :heart:

2 Likes

Your kind words mean a lot to me. Thank you!

1 Like

Release 0.10.0

Two new functions, add_idle_workers! and remove_idle_workers!, allow you to control the pool’s size at runtime.

For example, this is how you can add additional workers to an already running pool:

Poolex.add_idle_workers!(:my_lovely_pool, 5)

Dynamic pool size management can help you utilize resources more efficiently, depending on the workload.


Poolex package on Hex

3 Likes