Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions integration_test/ownership/manager_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,35 @@ defmodule ManagerTest do
assert log =~ "** (RuntimeError) oops"
end

test "includes label in ownership error when label is provided" do
if function_exported?(:proc_lib, :get_label, 1) do
{:ok, pool, opts} = start_pool(label: TestRepo)

error =
assert_raise DBConnection.OwnershipError, fn ->
P.run(pool, fn _ -> :ok end, opts)
end

assert error.message =~ "cannot find ownership process"
assert error.message =~ "using mode :manual"

assert error.message =~ "(TestRepo)"
end
end

test "doesn't require a label to produce an ownership error" do
{:ok, pool, opts} = start_pool()

# Try to use the pool without checking out - should raise OwnershipError
error =
assert_raise DBConnection.OwnershipError, fn ->
P.run(pool, fn _ -> :ok end, opts)
end

assert error.message =~ "cannot find ownership process"
assert error.message =~ "using mode :manual"
end

defp start_pool(opts \\ []) do
stack = [{:ok, :state}] ++ List.duplicate({:idle, :state}, 10)
{:ok, agent} = A.start_link(stack)
Expand Down
11 changes: 10 additions & 1 deletion lib/db_connection/ownership/manager.ex
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ defmodule DBConnection.Ownership.Manager do
mode = Keyword.get(pool_opts, :ownership_mode, :auto)
checkout_opts = Keyword.take(pool_opts, [:ownership_timeout, :queue_target, :queue_interval])

if label = pool_opts[:label] do
Util.set_label({__MODULE__, label})
end

{:ok,
%{
pool: pool,
Expand Down Expand Up @@ -406,9 +410,14 @@ defmodule DBConnection.Ownership.Manager do
end

defp not_found({pid, _} = from, mode) do
label = Util.pool_label(self())
label_info = if label, do: "(#{inspect(label)}) ", else: ""

msg = """
cannot find ownership process for #{Util.inspect_pid(pid)}
using mode #{inspect(mode)}.
#{label_info}using mode #{inspect(mode)}.
(Note that a connection's mode reverts to :manual if its owner
terminates.)

When using ownership, you must manage connections in one
of the four ways:
Expand Down
17 changes: 16 additions & 1 deletion lib/db_connection/util.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,27 @@ defmodule DBConnection.Util do
"""
def set_label(label) do
if function_exported?(Process, :set_label, 1) do
Process.set_label(label)
apply(Process, :set_label, [label])
else
:ok
end
end

@doc """
Get the pool label from a pid's process label.

Returns the label if found, or `nil` otherwise.
Process labels set as `{module, label}` tuples have the label extracted.
"""
def pool_label(pid) when is_pid(pid) do
case get_label(pid) do
{module, label} when is_atom(module) and module != nil and label != nil -> label
_ -> nil
end
end

def pool_label(_other), do: nil

# Get a process label if `:proc_lib.get_label/1` is available.
defp get_label(pid) do
if function_exported?(:proc_lib, :get_label, 1) do
Expand Down
Loading