ExPool v0.1.1 ExPool.Manager

Module to start a pool, and check-in and check-out workers.

When a worker is available, it can be checked-out from the pool. In case there are no available workers it will respond {:waiting, state} and enqueue the pending request.

When a worker is checked-in with any pending requests, it will respond with {:check_out, {requester_identifier, state}} and remove from de pending queue the current request.

Example:

defmodule HardWorker do
  def start_link(_), do: Agent.start_link(fn -> :ok end)
end

alias ExPool.Manager

state = Manager(worker_mod: HardWorker, size: 1)

# There is a worker available. It can be checked-out.
{:ok, {worker, state}} = Manager.check_out(state, :request_1)

# There are no workers available. The current request identified
# by :request_2 has to wait for available workers.
{:waiting, state} = Manager.check_out(state, :request_2)

# A worker is checked-in but there is a request pending. The
# worker is checked_out to be used by the pending request (:request_2).
{:check_out, {:request_2, state}} = Manager.check_in(state, worker)

# There are no pending requests. The worker is checked-in properly.
{:ok, state} = Manager.check_in(state, worker)

Summary

Functions

Check-in a worker from the pool

Check-out a worker from the pool

Gathers information about the current state of the pool

Create a new pool state with the given configuration. (See State.new/1 for more info about configuration options)

Handle a process down

Functions

check_in(state, worker)

Specs

check_in(ExPool.State.t, pid) ::
  {:ok, ExPool.State.t} |
  {:check_out, {from :: any, worker :: pid, ExPool.State.t}}

Check-in a worker from the pool.

When returning a worker to the pool, there are 2 possible scenarios:

  • There aren’t any worker requests pending: The worker is stored in the pool and responds with {:ok, state}.

  • There is any worker request pending: The worker is not stored. Instead the term identifying the request (from) is returned expecting the caller to yield the resource to the requester. It responds with {:check_out, {from, worker, state}.
check_out(state, from)

Specs

check_out(ExPool.State.t, from :: any) ::
  {:ok, {pid, ExPool.State.t}} |
  {:waiting, ExPool.State.t}

Check-out a worker from the pool.

It receives the state, and a term to identify the current check-out request. In case there are no workers available, the same term will be returned by check-in to identify the requester of the worker.

info(state)

Specs

info(ExPool.State.t) :: map

Gathers information about the current state of the pool.

Format:

%{

workers: %{
  free: <number_of_available_workers>,
  in_use: <number_of_workers_in_use>,
  total: <total_number_of_workers>
},
waiting: <number_of_processes_waiting_for_an_available_worker>

}

new(config)

Specs

new(config :: [Keyword]) :: ExPool.State.t

Create a new pool state with the given configuration. (See State.new/1 for more info about configuration options)

process_down(state, ref)

Specs

process_down(ExPool.State.t, reference) :: any

Handle a process down.

There are 2 types of monitored processes that can crash:

  • worker - If the crashed process is a worker, a new one is started and monitored

  • client - If the crashed process is a client, the worker that the process was using is returned to the pool