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

timeout_helpers.rb « migrations « database « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 423c77452b17be42382ee82d6dd68831ea3b249e (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
57
58
59
60
61
# frozen_string_literal: true

module Gitlab
  module Database
    module Migrations
      module TimeoutHelpers
        # Long-running migrations may take more than the timeout allowed by
        # the database. Disable the session's statement timeout to ensure
        # migrations don't get killed prematurely.
        #
        # There are two possible ways to disable the statement timeout:
        #
        # - Per transaction (this is the preferred and default mode)
        # - Per connection (requires a cleanup after the execution)
        #
        # When using a per connection disable statement, code must be inside
        # a block so we can automatically execute `RESET statement_timeout` after block finishes
        # otherwise the statement will still be disabled until connection is dropped
        # or `RESET statement_timeout` is executed
        def disable_statement_timeout
          if block_given?
            if statement_timeout_disabled?
              # Don't do anything if the statement_timeout is already disabled
              # Allows for nested calls of disable_statement_timeout without
              # resetting the timeout too early (before the outer call ends)
              yield
            else
              begin
                execute('SET statement_timeout TO 0')

                yield
              ensure
                execute('RESET statement_timeout')
              end
            end
          else
            unless transaction_open?
              raise <<~ERROR
                Cannot call disable_statement_timeout() without a transaction open or outside of a transaction block.
                If you don't want to use a transaction wrap your code in a block call:

                disable_statement_timeout { # code that requires disabled statement here }

                This will make sure statement_timeout is disabled before and reset after the block execution is finished.
              ERROR
            end

            execute('SET LOCAL statement_timeout TO 0')
          end
        end

        private

        def statement_timeout_disabled?
          # This is a string of the form "100ms" or "0" when disabled
          connection.select_value('SHOW statement_timeout') == "0"
        end
      end
    end
  end
end