未验证 提交 4fb9e239 编写于 作者: G George Claghorn 提交者: GitHub

Fix establishing connections for models with custom connection specification names

We have an internal engine whose models, for backwards compatibility with older Rails versions, override #connection_specification_name to connect to a shared DB rather than using Rails 6 multi-DB support.

b8fc0150 changed ActiveRecord::ConnectionAdapters::ConnectionPool#retrieve_connection_pool to pass ActiveRecord::DatabaseConfigurations::DatabaseConfig#config_hash to #establish_connection where it previously passed ActiveRecord::ConnectionAdapters::ConnectionSpecification#to_hash. But DatabaseConfig#config_hash does not include the specification name, so #establish_connection falls back to `"primary"`. The host app's primary DB connections and our engine's shared DB connections get mixed in the same pool as a result. Engine models will sometimes erroneously check out app DB connections and app models will sometimes check out engine DB connections.

To fix, we merge the connection specification name into the DB config hash before passing it into ConnectionPool#establish_connection.
上级 3322e23c
......@@ -1164,7 +1164,7 @@ def retrieve_connection_pool(spec_name)
# A connection was established in an ancestor process that must have
# subsequently forked. We can't reuse the connection, but we can copy
# the specification and establish a new connection with it.
establish_connection(ancestor_pool.spec.db_config.configuration_hash).tap do |pool|
establish_connection(ancestor_pool.spec.db_config.configuration_hash.merge(name: spec_name)).tap do |pool|
pool.schema_cache = ancestor_pool.schema_cache if ancestor_pool.schema_cache
end
else
......
......@@ -353,6 +353,28 @@ def test_forked_child_recovers_from_disconnected_parent
end
end
def test_retrieve_connection_pool_preserves_connection_specification_name
rd, wr = IO.pipe
rd.binmode
wr.binmode
@handler.establish_connection ActiveRecord::Base.configurations["arunit"].merge(name: "foo")
pid = fork {
rd.close
pool = @handler.retrieve_connection_pool("foo")
wr.write pool.spec.name
wr.close
exit!
}
wr.close
Process.waitpid pid
assert_equal "foo", rd.read
rd.close
end
def test_retrieve_connection_pool_copies_schema_cache_from_ancestor_pool
@pool.schema_cache = @pool.connection.schema_cache
@pool.schema_cache.add("posts")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册