# 🙅♂️ 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}