Raise specific exception when a connection is not defined
Co-authored-by: Matthew Draper <matthewd@github.com>
This commit is contained in:
parent
7b1ceb7659
commit
0bdf44d921
@ -1,3 +1,9 @@
|
|||||||
|
* Raise specific exception when a connection is not defined.
|
||||||
|
|
||||||
|
The new `ConnectionNotDefined` exception provides connection name, shard and role accessors indicating the details of the connection that was requested.
|
||||||
|
|
||||||
|
*Hana Harencarova*, *Matthew Draper*
|
||||||
|
|
||||||
* Delete the deprecated constant `ActiveRecord::ImmutableRelation`.
|
* Delete the deprecated constant `ActiveRecord::ImmutableRelation`.
|
||||||
|
|
||||||
*Xavier Noria*
|
*Xavier Noria*
|
||||||
|
@ -210,18 +210,25 @@ def remove_connection_pool(connection_name, role: ActiveRecord::Base.current_rol
|
|||||||
# This makes retrieving the connection pool O(1) once the process is warm.
|
# This makes retrieving the connection pool O(1) once the process is warm.
|
||||||
# When a connection is established or removed, we invalidate the cache.
|
# When a connection is established or removed, we invalidate the cache.
|
||||||
def retrieve_connection_pool(connection_name, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard, strict: false)
|
def retrieve_connection_pool(connection_name, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard, strict: false)
|
||||||
pool = get_pool_manager(connection_name)&.get_pool_config(role, shard)&.pool
|
pool_manager = get_pool_manager(connection_name)
|
||||||
|
pool = pool_manager&.get_pool_config(role, shard)&.pool
|
||||||
|
|
||||||
if strict && !pool
|
if strict && !pool
|
||||||
if shard != ActiveRecord::Base.default_shard
|
selector = [
|
||||||
message = "No connection pool for '#{connection_name}' found for the '#{shard}' shard."
|
("'#{shard}' shard" unless shard == ActiveRecord::Base.default_shard),
|
||||||
elsif role != ActiveRecord::Base.default_role
|
("'#{role}' role" unless role == ActiveRecord::Base.default_role),
|
||||||
message = "No connection pool for '#{connection_name}' found for the '#{role}' role."
|
].compact.join(" and ")
|
||||||
else
|
|
||||||
message = "No connection pool for '#{connection_name}' found."
|
|
||||||
end
|
|
||||||
|
|
||||||
raise ConnectionNotEstablished, message
|
selector = [
|
||||||
|
(connection_name unless connection_name == "ActiveRecord::Base"),
|
||||||
|
selector.presence,
|
||||||
|
].compact.join(" with ")
|
||||||
|
|
||||||
|
selector = " for #{selector}" if selector.present?
|
||||||
|
|
||||||
|
message = "No database connection defined#{selector}."
|
||||||
|
|
||||||
|
raise ConnectionNotDefined.new(message, connection_name: connection_name, shard: shard, role: role)
|
||||||
end
|
end
|
||||||
|
|
||||||
pool
|
pool
|
||||||
|
@ -1044,7 +1044,8 @@ def verified!
|
|||||||
end
|
end
|
||||||
|
|
||||||
def retryable_connection_error?(exception)
|
def retryable_connection_error?(exception)
|
||||||
exception.is_a?(ConnectionNotEstablished) || exception.is_a?(ConnectionFailed)
|
(exception.is_a?(ConnectionNotEstablished) && !exception.is_a?(ConnectionNotDefined)) ||
|
||||||
|
exception.is_a?(ConnectionFailed)
|
||||||
end
|
end
|
||||||
|
|
||||||
def invalidate_transaction(exception)
|
def invalidate_transaction(exception)
|
||||||
|
@ -84,6 +84,19 @@ def set_pool(connection_pool)
|
|||||||
class ConnectionTimeoutError < ConnectionNotEstablished
|
class ConnectionTimeoutError < ConnectionNotEstablished
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Raised when a database connection pool is requested but
|
||||||
|
# has not been defined.
|
||||||
|
class ConnectionNotDefined < ConnectionNotEstablished
|
||||||
|
def initialize(message = nil, connection_name: nil, role: nil, shard: nil)
|
||||||
|
super(message)
|
||||||
|
@connection_name = connection_name
|
||||||
|
@role = role
|
||||||
|
@shard = shard
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader :connection_name, :role, :shard
|
||||||
|
end
|
||||||
|
|
||||||
# Raised when connection to the database could not been established because it was not
|
# Raised when connection to the database could not been established because it was not
|
||||||
# able to connect to the host or when the authorization failed.
|
# able to connect to the host or when the authorization failed.
|
||||||
class DatabaseConnectionError < ConnectionNotEstablished
|
class DatabaseConnectionError < ConnectionNotEstablished
|
||||||
|
@ -359,13 +359,13 @@ def test_retrieve_connection_pool_with_invalid_id
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_calling_connected_to_on_a_non_existent_handler_raises
|
def test_calling_connected_to_on_a_non_existent_handler_raises
|
||||||
error = assert_raises ActiveRecord::ConnectionNotEstablished do
|
error = assert_raises ActiveRecord::ConnectionNotDefined do
|
||||||
ActiveRecord::Base.connected_to(role: :non_existent) do
|
ActiveRecord::Base.connected_to(role: :non_existent) do
|
||||||
Person.first
|
Person.first
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_equal "No connection pool for 'ActiveRecord::Base' found for the 'non_existent' role.", error.message
|
assert_equal "No database connection defined for 'non_existent' role.", error.message
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_default_handlers_are_writing_and_reading
|
def test_default_handlers_are_writing_and_reading
|
||||||
|
@ -21,7 +21,7 @@ def test_establishing_a_connection_in_connected_to_block_uses_current_role_and_s
|
|||||||
ActiveRecord::Base.establish_connection(db_config)
|
ActiveRecord::Base.establish_connection(db_config)
|
||||||
assert_nothing_raised { Person.first }
|
assert_nothing_raised { Person.first }
|
||||||
|
|
||||||
assert_equal [:default, :shard_one], ActiveRecord::Base.connection_handler.send(:get_pool_manager, "ActiveRecord::Base").shard_names
|
assert_equal [:default, :shard_one].sort, ActiveRecord::Base.connection_handler.send(:get_pool_manager, "ActiveRecord::Base").shard_names.sort
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -233,13 +233,51 @@ def test_calling_connected_to_on_a_non_existent_shard_raises
|
|||||||
default: { writing: :arunit, reading: :arunit }
|
default: { writing: :arunit, reading: :arunit }
|
||||||
})
|
})
|
||||||
|
|
||||||
error = assert_raises ActiveRecord::ConnectionNotEstablished do
|
error = assert_raises ActiveRecord::ConnectionNotDefined do
|
||||||
ActiveRecord::Base.connected_to(role: :reading, shard: :foo) do
|
ActiveRecord::Base.connected_to(role: :reading, shard: :foo) do
|
||||||
Person.first
|
Person.first
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_equal "No connection pool for 'ActiveRecord::Base' found for the 'foo' shard.", error.message
|
assert_equal "No database connection defined for 'foo' shard and 'reading' role.", error.message
|
||||||
|
assert_equal "ActiveRecord::Base", error.connection_name
|
||||||
|
assert_equal :foo, error.shard
|
||||||
|
assert_equal :reading, error.role
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_calling_connected_to_on_a_non_existent_role_for_shard_raises
|
||||||
|
ActiveRecord::Base.connects_to(shards: {
|
||||||
|
default: { writing: :arunit, reading: :arunit },
|
||||||
|
shard_one: { writing: :arunit, reading: :arunit }
|
||||||
|
})
|
||||||
|
|
||||||
|
error = assert_raises ActiveRecord::ConnectionNotDefined do
|
||||||
|
ActiveRecord::Base.connected_to(role: :non_existent, shard: :shard_one) do
|
||||||
|
Person.first
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal "No database connection defined for 'shard_one' shard and 'non_existent' role.", error.message
|
||||||
|
assert_equal "ActiveRecord::Base", error.connection_name
|
||||||
|
assert_equal :shard_one, error.shard
|
||||||
|
assert_equal :non_existent, error.role
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_calling_connected_to_on_a_default_role_for_non_existent_shard_raises
|
||||||
|
ActiveRecord::Base.connects_to(shards: {
|
||||||
|
default: { writing: :arunit, reading: :arunit }
|
||||||
|
})
|
||||||
|
|
||||||
|
error = assert_raises ActiveRecord::ConnectionNotDefined do
|
||||||
|
ActiveRecord::Base.connected_to(shard: :foo) do
|
||||||
|
Person.first
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal "No database connection defined for 'foo' shard.", error.message
|
||||||
|
assert_equal "ActiveRecord::Base", error.connection_name
|
||||||
|
assert_equal :foo, error.shard
|
||||||
|
assert_equal :writing, error.role
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_cannot_swap_shards_while_prohibited
|
def test_cannot_swap_shards_while_prohibited
|
||||||
|
@ -1710,7 +1710,7 @@ def test_only_existing_connections_are_replaced
|
|||||||
|
|
||||||
setup_shared_connection_pool
|
setup_shared_connection_pool
|
||||||
|
|
||||||
assert_raises(ActiveRecord::ConnectionNotEstablished) do
|
assert_raises(ActiveRecord::ConnectionNotDefined) do
|
||||||
ActiveRecord::Base.connected_to(role: :reading, shard: :two) do
|
ActiveRecord::Base.connected_to(role: :reading, shard: :two) do
|
||||||
ActiveRecord::Base.retrieve_connection
|
ActiveRecord::Base.retrieve_connection
|
||||||
end
|
end
|
||||||
@ -1721,7 +1721,7 @@ def test_only_existing_connections_are_restored
|
|||||||
clean_up_connection_handler
|
clean_up_connection_handler
|
||||||
teardown_shared_connection_pool
|
teardown_shared_connection_pool
|
||||||
|
|
||||||
assert_raises(ActiveRecord::ConnectionNotEstablished) do
|
assert_raises(ActiveRecord::ConnectionNotDefined) do
|
||||||
ActiveRecord::Base.connected_to(role: :reading) do
|
ActiveRecord::Base.connected_to(role: :reading) do
|
||||||
ActiveRecord::Base.retrieve_connection
|
ActiveRecord::Base.retrieve_connection
|
||||||
end
|
end
|
||||||
|
@ -23,21 +23,21 @@ def setup
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_connection_no_longer_established
|
def test_connection_no_longer_established
|
||||||
assert_raise(ActiveRecord::ConnectionNotEstablished) do
|
assert_raise(ActiveRecord::ConnectionNotDefined) do
|
||||||
TestRecord.find(1)
|
TestRecord.find(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_raise(ActiveRecord::ConnectionNotEstablished) do
|
assert_raise(ActiveRecord::ConnectionNotDefined) do
|
||||||
TestRecord.new.save
|
TestRecord.new.save
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_error_message_when_connection_not_established
|
def test_error_message_when_connection_not_established
|
||||||
error = assert_raise(ActiveRecord::ConnectionNotEstablished) do
|
error = assert_raise(ActiveRecord::ConnectionNotDefined) do
|
||||||
TestRecord.find(1)
|
TestRecord.find(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_equal "No connection pool for 'ActiveRecord::Base' found.", error.message
|
assert_equal "No database connection defined.", error.message
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_underlying_adapter_no_longer_active
|
def test_underlying_adapter_no_longer_active
|
||||||
|
Loading…
Reference in New Issue
Block a user