File: database_connection.rb

package info (click to toggle)
gitlab 17.6.5-19
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 629,368 kB
  • sloc: ruby: 1,915,304; javascript: 557,307; sql: 60,639; xml: 6,509; sh: 4,567; makefile: 1,239; python: 406
file content (71 lines) | stat: -rw-r--r-- 2,075 bytes parent folder | download
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# frozen_string_literal: true

module Backup
  class DatabaseConnection
    attr_reader :database_configuration, :snapshot_id

    delegate :connection_name, to: :database_configuration
    delegate :connection, to: :@backup_model

    # Initializes a database connection
    #
    # @param [String] connection_name the key from `database.yml` for multi-database connection configuration
    def initialize(connection_name)
      @database_configuration = Backup::DatabaseConfiguration.new(connection_name)
      @backup_model = backup_model
      @snapshot_id = nil

      configure_backup_model
    end

    # Start a new transaction and run pg_export_snapshot()
    # Returns the snapshot identifier
    #
    # @return [String] snapshot identifier
    def export_snapshot!
      disable_timeouts!

      connection.begin_transaction(isolation: :repeatable_read)
      @snapshot_id = connection.select_value("SELECT pg_export_snapshot()")
    end

    # Rollback the transaction to release the effects of pg_export_snapshot()
    def release_snapshot!
      return unless snapshot_id

      connection.rollback_transaction
      @snapshot_id = nil
    end

    def disable_timeouts!
      transaction_timeout_settings.disable_timeouts
    end

    def restore_timeouts!
      transaction_timeout_settings.restore_timeouts
    end

    private

    delegate :activerecord_configuration, to: :database_configuration, private: true

    def configure_backup_model
      @backup_model.establish_connection(activerecord_configuration)

      Gitlab::Database::LoadBalancing::Setup.new(@backup_model).setup
    end

    # Creates a disposable model to be used to host the Backup connection only
    def backup_model
      klass_name = connection_name.camelize

      return "#{self.class.name}::#{klass_name}".constantize if self.class.const_defined?(klass_name.to_sym, false)

      self.class.const_set(klass_name, Class.new(ApplicationRecord))
    end

    def transaction_timeout_settings
      Gitlab::Database::TransactionTimeoutSettings.new(connection)
    end
  end
end