Hi
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!
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