From 26650954aff1452be6319a4bb035473bfa3f3729 Mon Sep 17 00:00:00 2001 From: Nathan Long Date: Tue, 28 Oct 2025 09:26:25 -0400 Subject: [PATCH] Put a label (like Repo name) in these errors The label must be passed in - see https://github.com/elixir-ecto/ecto_sql/pull/698/ Assuming it's the repo name, this is helpful if the application has more than one repo (eg read replicas). For example: Before: "** (DBConnection.ConnectionError) connection is closed because of an error, disconnect or timeout" After: "** (DBConnection.ConnectionError) MyApp.Repo connection is closed because of an error, disconnect or timeout" --- lib/db_connection/holder.ex | 26 ++++++++++++++++++++++---- lib/db_connection/ownership/manager.ex | 11 +++++++---- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/lib/db_connection/holder.ex b/lib/db_connection/holder.ex index e8f399c..33f4b61 100644 --- a/lib/db_connection/holder.ex +++ b/lib/db_connection/holder.ex @@ -137,18 +137,32 @@ defmodule DBConnection.Holder do :ets.lookup(holder, :conn) rescue ArgumentError -> - msg = "connection is closed because of an error, disconnect or timeout" + msg = + maybe_prefix_label( + "connection is closed because of an error, disconnect or timeout", + opts + ) + {:disconnect, DBConnection.ConnectionError.exception(msg), _state = :unused} else [conn(lock: conn_lock)] when conn_lock != lock -> - raise "an outdated connection has been given to DBConnection on #{fun}/#{length(args) + 2}" + raise maybe_prefix_label( + "an outdated connection has been given to DBConnection on #{fun}/#{length(args) + 2}", + opts, + ":" + ) [conn(status: :error)] -> - msg = "connection is closed because of an error, disconnect or timeout" + msg = + maybe_prefix_label( + "connection is closed because of an error, disconnect or timeout", + opts + ) + {:disconnect, DBConnection.ConnectionError.exception(msg), _state = :unused} [conn(status: :aborted)] when type != :cleanup -> - msg = "transaction rolling back" + msg = maybe_prefix_label("transaction rolling back", opts) {:disconnect, DBConnection.ConnectionError.exception(msg), _state = :unused} [conn(module: module, state: state)] -> @@ -156,6 +170,10 @@ defmodule DBConnection.Holder do end end + defp maybe_prefix_label(msg, opts, separator \\ "") do + if opts[:label], do: "#{inspect(opts[:label])} " <> separator <> msg, else: msg + end + ## Pool state helpers API (invoked by callers) @spec put_state(pool_ref :: any, term) :: :ok diff --git a/lib/db_connection/ownership/manager.ex b/lib/db_connection/ownership/manager.ex index 482bc7b..aeb9ab1 100644 --- a/lib/db_connection/ownership/manager.ex +++ b/lib/db_connection/ownership/manager.ex @@ -107,7 +107,8 @@ defmodule DBConnection.Ownership.Manager do mode: mode, mode_ref: nil, ets: ets, - log: log + log: log, + label: pool_opts[:label] }} end @@ -223,7 +224,7 @@ defmodule DBConnection.Ownership.Manager do {:noreply, state} :not_found when mode == :manual -> - not_found(from, mode) + not_found(from, mode, state.label) {:noreply, state} :not_found -> @@ -405,10 +406,12 @@ defmodule DBConnection.Ownership.Manager do caller end - defp not_found({pid, _} = from, mode) do + defp not_found({pid, _} = from, mode, label) do msg = """ cannot find ownership process for #{Util.inspect_pid(pid)} - using mode #{inspect(mode)}. + #{if label, do: "(#{inspect(label)})"} 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: