# 🙅♂️ PoolLad
`pool_lad` is the younger & more energetic version of [`:poolboy`](https://github.com/devinus/poolboy).
It's still the _**lightweight, generic pooling library with focus on
simplicity, performance, and rock-solid disaster recovery**_ that we all love...
...but it has just gotten a much needed facelift!
## Table of contents
- [Installation](#installation)
- [Documentation](#documentation)
- [Sample usage](#sample-usage)
## Installation
Add `:pool_lad` as a dependency to your project's `mix.exs`:
```elixir
defp deps do
[
{:pool_lad, "~> 0.0.1"}
]
end
```
## Documentation
The full documentation is [published on hex](https://hexdocs.pm/pool_lad/).
## Sample usage
The APIs are almost identical to those of [`:poolboy`](https://github.com/devinus/poolboy).
Via manual ownership:
```elixir
iex(1)> {:ok, pid} = PoolLad.borrow(MyWorkerPool)
{:ok, #PID<0.229.0>}
iex(2)> GenServer.call(pid, :get_latest_count)
{:ok, 42}
iex(3)> PoolLad.return(MyWorkerPool, pid)
:ok
```
Via transactional ownership:
```elixir
iex(1)> PoolLad.transaction(
MyWorkerPool,
fn pid -> GenServer.call(pid, :get_latest_count) end
)
{:ok, 42}
```
## Why PoolLad over poolboy
- Elixir-first
- Modern APIs, e.g. `DynamicSupervisor`
- Less code, less pesky logs, less noise
- More documentation
- Same performance
- Maintained
## TODO
- [ ] Add overflow functionality
- [ ] Clean up the below docs
### 1. Define a worker
This would ideally be a `GenServer`, but can be any module that implements `child_spec/1`.
defmodule MyWorker do
use GenServer
@this_module __MODULE__
def start_link(opts) do
initial_count = Keyword.get(opts, :initial_count, 0)
GenServer.start_link(@this_module, initial_count)
end
@impl true
def init(initial_count), do: {:ok, initial_count}
@impl true
def handle_call(:get_latest_count, _from, count), do: {reply, count, count}
end
ℹ️ Please note that workers should not be "named" as multiple instances of the same
worker will be started by the `PoolLad`'s dedicated `DynamicSupervisor`.
### 2. Start the pool
You'd usually start your worker pool as a child under a `Supervisor`.
pool_opts = [name: MyWorkerPool, worker_count: 3, worker_module: MyWorker]
worker_opts = [initial_count: 42]
children = [
{PoolLad, {pool_opts, worker_opts}}
]
Supervisor.start_link(children, strategy: :one_for_one)
### 3. Do the work
iex> PoolLad.transaction(
MyWorkerPool,
fn pid -> GenServer.call(pid, :get_latest_count) end
)
{:ok, 42}
Once you're ready to use the worker, make sure you claim its ownership.
{:ok, pid} = PoolLad.borrow(MyWorkerPool)
### 4. Do the work
Now that you've claimed unique ownership of the pid, you can use it to perform
the work you need.
iex> GenServer.call(pid, :get_latest_count)
{:ok, 42}
### 5. Return the worker
the pid back to the pool so other processes can borrow it it
:ok = PoolLad.return(MyWorkerPool, pid)
### Simplify
ℹ️ You can make this a little easier by using `transaction/3`.
iex> PoolLad.transaction(
MyWorkerPool,
fn pid -> GenServer.call(pid, :get_latest_count) end
)
{:ok, 42}