pool_sup v0.1.0 PoolSup
This module defines a supervisor process that is specialized to manage pool of workers.
- Process defined by this module behaves as a
:simple_one_for_onesupervisor. - Worker processes are spawned using a callback module that implements
PoolSup.Workerbehaviour. - The
PoolSupprocess manages which child processes are in use and which are not. - Functions to request pid of a child process that is not in use are also defined.
Example
Suppose we have a module that implements both GenServer and PoolSup.Worker behaviours.
iex(1)> defmodule MyWorker do
...(1)> @behaviour PoolSup.Worker
...(1)> use GenServer
...(1)> def start_link(arg) do
...(1)> GenServer.start_link(__MODULE__, arg)
...(1)> end
...(1)> # definitions of gen_server callbacks...
...(1)> end
When we want to have 3 processes that run MyWorker server:
iex(2)> {:ok, pid} = PoolSup.start_link(MyWorker, {:worker, :arg}, 3, [name: :my_pool])
Each child process is started by MyWorker.start_link({:worker, :arg}).
Then we can get a pid of a child currently not in use.
iex(3)> child_pid = PoolSup.checkout(:my_pool)
iex(4)> do_something(child_pid)
iex(5)> PoolSup.checkin(:my_pool, child_pid)
Don’t forget to return the child_pid when finished; for simple use cases PoolSup.transaction/3 comes in handy.
Usage within supervision tree
The following code snippet spawns a supervisor that has PoolSup process as one of its children.
The PoolSup process manages 5 worker processes and they will be started by MyWorker.start_link({:worker, :arg}).
chilldren = [
...
Supervisor.Spec.supervisor(PoolSup, [MyWorker, {:worker, :arg}, 5]),
...
]
Supervisor.start_link(children, [strategy: :one_for_one])
Summary
Functions
Changes capacity (number of worker processes) of a pool
Checks in an in-use worker process and make it available to others
Checks out a worker pid that is currently not used
Checks out a worker pid in a nonblocking manner, i.e. if no available worker found this returns nil
Starts a PoolSup process linked to the calling process
Query current status of a pool
Temporarily checks out a worker pid, executes the given function using the pid, and checks in the pid
Types
options :: [{:name, GenServer.name}]
pool :: pid | GenServer.name
Functions
Specs
change_capacity(pool, non_neg_integer) :: :ok
Changes capacity (number of worker processes) of a pool.
If new_capacity is more than the current capacity, new processes are immediately spawned and become available.
Note that, as is the same throughout the OTP framework, spawning processes under supervisor is synchronous operation.
Therefore increasing large number of capacity at once may make a pool unresponsive for a while.
If new_capacity is less than the current capacity, the pool tries to shutdown workers that are not in use.
Processes currently in use are never interrupted.
If number of in-use workers is more than new_capacity, reducing further is delayed until any worker process is checked in.
Specs
checkin(pool, pid) :: :ok
Checks in an in-use worker process and make it available to others.
Specs
checkout(pool, timeout) :: nil | pid
Checks out a worker pid that is currently not used.
If no available worker process exists, the caller is blocked until either
- any process becomes available, or
- timeout is reached.
Specs
checkout_nonblock(pool, timeout) :: nil | pid
Checks out a worker pid in a nonblocking manner, i.e. if no available worker found this returns nil.
Specs
start_link(module, term, non_neg_integer, options) :: GenServer.on_start
Starts a PoolSup process linked to the calling process.
Arguments
worker_moduleis the callback module ofPoolSup.Worker.worker_init_argis the value passed toworker_module.start_link/1callback function.capacityis the initial number of workers thisPoolSupprocess holds.- Currently only
:nameoption is supported for name registration.
Specs
status(pool) :: %{current_capacity: nni, desired_capacity: nni, available: nni, working: nni} when nni: non_neg_integer
Query current status of a pool.
Specs
transaction(pool, (pid -> a), timeout) :: a when a: any
Temporarily checks out a worker pid, executes the given function using the pid, and checks in the pid.
The timeout parameter is used only in the checkout step; time elapsed during other steps are not counted.