Welcome to mirror list, hosted at ThFree Co, Russian Federation.

reestablished_connection_stack.rb « migrations « database « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: d7cf482c32aab17490460758d032a5da8cd0de1a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# frozen_string_literal: true

module Gitlab
  module Database
    module Migrations
      module ReestablishedConnectionStack
        # This is workaround for `db:migrate` that switches `ActiveRecord::Base.connection`
        # depending on execution. This is subject to be removed once proper fix is implemented:
        # https://gitlab.com/gitlab-org/gitlab/-/issues/362341
        #
        # In some cases when we run application code we need to restore application connection stack:
        # - ApplicationRecord (in fact ActiveRecord::Base): points to main
        # - Ci::ApplicationRecord: points to ci
        #
        # rubocop:disable Database/MultipleDatabases
        def with_restored_connection_stack(&block)
          original_handler = ActiveRecord::Base.connection_handler

          original_db_config = ActiveRecord::Base.connection_db_config
          return yield if ActiveRecord::Base.configurations.primary?(original_db_config.name)

          # If the `ActiveRecord::Base` connection is different than `:main`
          # re-establish and configure `SharedModel` context accordingly
          # to previously established `ActiveRecord::Base` to allow the application
          # code to use `ApplicationRecord` and `Ci::ApplicationRecord` usual way.
          # We swap a connection handler as migration context does hold an actual
          # connection which we cannot close.
          base_model = Gitlab::Database.database_base_models.fetch(original_db_config.name.to_sym)

          # copy connections over to new connection handler
          db_configs = original_handler.connection_pool_names.map do |connection_pool_name|
            [connection_pool_name.constantize, connection_pool_name.constantize.connection_db_config]
          end

          new_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
          ActiveRecord::Base.connection_handler = new_handler

          db_configs.each do |klass, db_config|
            new_handler.establish_connection(db_config, owner_name: klass)
          end

          # re-establish ActiveRecord::Base to main
          ActiveRecord::Base.establish_connection :main # rubocop:disable Database/EstablishConnection

          Gitlab::Database::SharedModel.using_connection(base_model.connection) do
            yield
          end
        ensure
          ActiveRecord::Base.connection_handler = original_handler
          new_handler&.clear_all_connections!
        end
        # rubocop:enable Database/MultipleDatabases
      end
    end
  end
end