Packages
ecto
1.0.3
3.14.1
3.14.0
3.13.6
3.13.5
3.13.4
3.13.3
3.13.2
3.13.1
3.13.0
3.12.6
3.12.5
3.12.4
3.12.3
3.12.2
3.12.1
3.12.0
3.11.2
3.11.1
3.11.0
3.10.3
3.10.2
3.10.1
3.10.0
3.9.6
3.9.5
3.9.4
3.9.3
3.9.2
3.9.1
3.9.0
3.8.4
3.8.3
3.8.2
3.8.1
3.8.0
3.7.2
3.7.1
3.7.0
3.6.2
3.6.1
3.6.0
3.5.8
3.5.7
3.5.6
3.5.5
3.5.4
3.5.3
3.5.2
3.5.1
3.5.0
3.5.0-rc.1
3.5.0-rc.0
3.4.6
3.4.5
3.4.4
3.4.3
3.4.2
3.4.1
3.4.0
3.3.4
3.3.3
3.3.2
3.3.1
3.3.0
3.2.5
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.9
3.0.8
3.0.7
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
3.0.0-rc.1
3.0.0-rc.0
2.2.12
2.2.11
2.2.10
2.2.9
2.2.8
2.2.7
2.2.6
2.2.5
2.2.4
2.2.3
2.2.2
2.2.1
2.2.0
2.2.0-rc.1
2.2.0-rc.0
2.1.6
2.1.5
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.1.0-rc.5
2.1.0-rc.4
2.1.0-rc.3
2.1.0-rc.2
2.1.0-rc.1
2.1.0-rc.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.6
2.0.0-rc.5
2.0.0-rc.4
2.0.0-rc.3
2.0.0-rc.2
2.0.0-rc.1
2.0.0-rc.0
2.0.0-beta.2
2.0.0-beta.1
2.0.0-beta.0
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.16.0
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.1
0.13.0
0.12.1
0.12.0
0.12.0-rc
0.11.3
0.11.2
0.11.1
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.0
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.0
0.5.1
0.5.0
0.4.0
0.3.0
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.0
A toolkit for data mapping and language integrated query for Elixir
Current section
Files
Jump to
Current section
Files
lib/ecto/pools/sojourn_broker.ex
defmodule Ecto.Pools.SojournBroker do
@moduledoc """
Start a pool of connections using `sbroker`.
### Options
* `:pool_name` - The name of the pool supervisor
* `:pool_size` - The number of connections to keep in the pool (default: 10)
* `:min_backoff` - The minimum backoff on failed connect in milliseconds (default: 50)
* `:max_backoff` - The maximum backoff on failed connect in milliseconds (default: 5000)
* `:broker` - The `sbroker` module to use (default: `Ecto.Pools.SojournBroker.Timeout`)
* `:lazy` - When true, initial connections to the repo are lazily started (default: true)
* `:shutdown` - The shutdown method for the connections (default: 5000) (see Supervisor.Spec)
"""
alias Ecto.Pools.SojournBroker.Worker
@behaviour Ecto.Pool
@doc """
Starts a pool of connections for the given connection module and options.
* `conn_mod` - The connection module, see `Ecto.Adapters.Connection`
* `opts` - The options for the pool, the broker and the connections
"""
def start_link(conn_mod, opts) do
{:ok, _} = Application.ensure_all_started(:sbroker)
{name, mod, size, opts} = split_opts(opts)
import Supervisor.Spec
args = [{:local, name}, mod, opts, [time_unit: :micro_seconds]]
broker = worker(:sbroker, args)
workers = for id <- 1..size do
worker(Worker, [conn_mod, name, opts], [id: id])
end
worker_sup_opts = [strategy: :one_for_one, max_restarts: size]
worker_sup = supervisor(Supervisor, [workers, worker_sup_opts])
children = [broker, worker_sup]
sup_opts = [strategy: :rest_for_one, name: Module.concat(name, Supervisor)]
Supervisor.start_link(children, sup_opts)
end
@doc false
def checkout(pool, timeout) do
ask(pool, :run, timeout)
end
@doc false
def checkin(_, {worker, ref}, _) do
Worker.done(worker, ref)
end
@doc false
def open_transaction(pool, timeout) do
ask(pool, :transaction, timeout)
end
@doc false
def close_transaction(_, {worker, ref}, _) do
Worker.done(worker, ref)
end
@doc false
def break(_, {worker, ref}, timeout) do
Worker.break(worker, ref, timeout)
end
## Helpers
defp ask(pool, fun, timeout) do
case :sbroker.ask(pool, {fun, self()}) do
{:go, ref, {worker, :lazy}, _, queue_time} ->
lazy_connect(worker, ref, queue_time, timeout)
{:go, ref, {worker, mod_conn}, _, queue_time} ->
{:ok, {worker, ref}, mod_conn, queue_time}
{:drop, _} ->
{:error, :noconnect}
end
end
## Helpers
defp split_opts(opts) do
{pool_opts, conn_opts} = Keyword.split(opts, [:pool_name, :pool_size, :broker])
conn_opts =
conn_opts
|> Keyword.put_new(:queue_timeout, Keyword.get(opts, :timeout, 5_000))
|> Keyword.put(:timeout, Keyword.get(opts, :connect_timeout, 5_000))
name = Keyword.fetch!(pool_opts, :pool_name)
broker = Keyword.get(pool_opts, :broker, Ecto.Pools.SojournBroker.Timeout)
size = Keyword.get(pool_opts, :pool_size, 10)
{name, broker, size, conn_opts}
end
defp lazy_connect(worker, ref, queue_time, timeout) do
try do
:timer.tc(Worker, :mod_conn, [worker, ref, timeout])
catch
class, reason ->
stack = System.stacktrace()
Worker.done(worker, ref)
:erlang.raise(class, reason, stack)
else
{connect_time, {:ok, mod_conn}} ->
{:ok, {worker, ref}, mod_conn, queue_time + connect_time}
{_, {:error, :noconnect} = error} ->
Worker.done(worker, ref)
error
end
end
end