61 lines
2.2 KiB
Ruby
61 lines
2.2 KiB
Ruby
# 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
|