Allow nesting of SharedModel.using_connection
What does this MR do and why?
Related to #343047 (closed)
Allow SharedModel.using_connection
blocks to be nested as long as they use the same connection object. This is useful for making background migrations compatible with multiple databases, because we have several entry points and we want to ensure the shared connection is setup properly in each.
We can imagine that happening in code like this:
class BackgroundMigrationWorker
def perform(class_name, args)
Gitlab::Database::SharedModel.using_connection(connection) do
# other operations using a SharedModel
Gitlab::BackgroundMigration.perform(class_name, *rgs)
end
end
end
module Gitlab
module BackgroundMigration
def self.perform(class_name, args)
Gitlab::Database::SharedModel.using_connection(connection) do
class_name.constantize.new.perform(*args)
end
end
end
end
We prefer to always setup the shared connection at the outermost level possible, so that future code changes are guaranteed to have the right connection. Sidekiq enters into running the job through BackgroundMigrationWorker#perform
, but other code may call BackgroundMigration.perform
directly. Typically we don't call this code directly outside of a migration context, but we want to guard against unexpected calls with the wrong connection.
We also still want to prevent setting multiple nested levels with different connections, since that seems unnecessary at this time and likely indicates something in our connection-handling logic is wrong.
How to set up and validate locally
The added test cases can be tried locally to verify that it works. Note that nested objects must be the same object, not just equivalent objects.
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
-
I have evaluated the MR acceptance checklist for this MR.