Packages
db_connection
0.1.4
2.10.2
2.10.1
2.10.0
2.9.0
2.8.1
2.8.0
2.7.0
2.6.0
2.5.0
2.4.3
2.4.2
2.4.1
2.4.0
2.3.1
2.3.0
2.2.2
2.2.1
2.2.0
2.1.1
2.1.0
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
2.0.0-rc.0
1.1.3
1.1.2
1.1.1
1.1.0
1.0.0
1.0.0-rc.5
1.0.0-rc.4
1.0.0-rc.3
1.0.0-rc.2
1.0.0-rc.1
1.0.0-rc.0
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Database connection behaviour for database transactions and connection pooling
Current section
Files
Jump to
Current section
Files
lib/db_connection/poolboy.ex
defmodule DBConnection.Poolboy do
@moduledoc """
A `DBConnection.Pool` using poolboy.
### Options
* `:pool_size` - The number of connections (default: `10`)
* `:pool_overflow` - The maximum number of overflow connections to
start if all connections are checked out (default: `0`)
* `:queue_out` - Either `:out` for a FIFO queue or `:out_r` for a
LIFO queue (default: `:out`)
"""
@behaviour DBConnection.Pool
@timeout 5000
@doc false
def start_link(mod, opts) do
{pool_opts, worker_opts} = pool_args(mod, opts)
:poolboy.start_link(pool_opts, worker_opts)
end
@doc false
def child_spec(mod, opts, child_opts) do
{pool_opts, worker_args} = pool_args(mod, opts)
id = Keyword.get(child_opts, :id, __MODULE__)
:poolboy.child_spec(id, pool_opts, worker_args)
end
@doc false
def checkout(pool, opts) do
queue_timeout = Keyword.get(opts, :queue_timeout, @timeout)
queue? = Keyword.get(opts, :queue, true)
case :poolboy.checkout(pool, queue?, queue_timeout) do
:full -> :error
worker -> checkout(pool, worker, opts)
end
end
@doc false
def checkin({pool, worker, worker_ref}, state, opts) do
:poolboy.checkin(pool, worker)
DBConnection.Connection.checkin(worker_ref, state, opts)
end
@doc false
def disconnect({pool, worker, worker_ref}, err, state, opts) do
:poolboy.checkin(pool, worker)
DBConnection.Connection.disconnect(worker_ref, err, state, opts)
end
@doc false
def stop({pool, worker, worker_ref}, reason, state, opts) do
# Synchronous stop is required to prevent checking in a worker thats
# about to exit as it can cause a client to get a worker thats about
# to exit.
try do
DBConnection.Connection.sync_stop(worker_ref, reason, state, opts)
after
:poolboy.checkin(pool, worker)
end
end
## Helpers
defp pool_args(mod, opts) do
pool_opts = [strategy: strategy(opts),
size: Keyword.get(opts, :pool_size, 10),
max_overflow: Keyword.get(opts, :pool_overflow, 0),
worker_module: DBConnection.Poolboy.Worker]
{name_opts(opts) ++ pool_opts, {mod, opts}}
end
defp strategy(opts) do
case Keyword.get(opts, :queue_out, :out) do
:out -> :fifo
:out_r -> :lifo
end
end
defp name_opts(opts) do
case Keyword.get(opts, :name) do
nil -> []
name when is_atom(name) -> [name: {:local, name}]
name -> [name: name]
end
end
defp checkout(pool, worker, opts) do
try do
DBConnection.Connection.checkout(worker, opts)
else
{:ok, worker_ref, mod, state} ->
{:ok, {pool, worker, worker_ref}, mod, state}
:error ->
:poolboy.checkin(pool, worker)
:error
catch
:exit, reason ->
:poolboy.checkin(pool, worker)
exit(reason)
end
end
end