Skip to content

Commit

Permalink
Merge pull request #13770 from opf/bugfix/do-not-set-statement-timeou…
Browse files Browse the repository at this point in the history
…t-if-already-set-to-0

Do not set statement timeout if already set to 0
  • Loading branch information
oliverguenther committed Sep 25, 2023
2 parents d9cec7c + 87dc4bd commit 7244ce3
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 38 deletions.
4 changes: 2 additions & 2 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ RSpec/DescribeMethod:

# Don't force the second argument of describe
# to match the exact file name
RSpec/FilePath:
SpecSuffixOnly: true
RSpec/SpecFilePathFormat:
IgnoreMethods: true

# Prevent "fit" or similar to be committed
RSpec/Focus:
Expand Down
105 changes: 69 additions & 36 deletions lib_static/open_project/migration_statement_timeout/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,74 @@

module MigrationStatementTimeout
module Manager
class SetMinimumStatementTimeout
attr_reader :conn

def initialize(conn, migration)
@conn = conn
@migration = migration
end

delegate :say, to: :@migration

def call(min_timeout)
if same_timeout?(min_timeout)
say "ignore set statement_timeout to #{min_timeout}: " \
"current statement timeout is already #{current_timeout}"
elsif current_timeout_disabled?
say "ignore set statement_timeout to #{min_timeout}: " \
"current statement timeout is disabled (value is 0)"
elsif current_timeout_is_greater_than?(min_timeout)
say "ignore set statement_timeout to #{min_timeout}: " \
"current statement timeout #{current_timeout} is greater"
else
set_timeout(min_timeout)
say "set statement_timeout to #{min_timeout} (was #{current_timeout} before)"
end
end

def current_timeout_disabled?
in_ms(current_timeout).zero?
end

def same_timeout?(min_timeout)
in_ms(current_timeout) == in_ms(min_timeout)
end

def current_timeout_is_greater_than?(min_timeout)
in_ms(min_timeout).positive? && in_ms(current_timeout) > in_ms(min_timeout)
end

def current_timeout
@current_timeout ||= get_timeout
end

def get_timeout
conn.execute('SHOW statement_timeout').first['statement_timeout']
end

def set_timeout(timeout)
conn.execute("SET LOCAL statement_timeout = '#{timeout}'")
end

def in_ms(timeout)
case timeout
when Integer
timeout
when /\A\d+(ms)?\z/
timeout.to_i
when /\A\d+s\z/
timeout.to_i * 1000
when /\A\d+min\z/
timeout.to_i * 1000 * 60
when /\A\d+h\z/
timeout.to_i * 1000 * 60 * 60
else
raise ArgumentError, "Unrecognized statement timeout duration #{timeout.inspect}"
end
end
end

def exec_migration(conn, direction)
min_timeout = self.class.minimum_statement_timeout
return super unless min_timeout
Expand All @@ -40,44 +108,9 @@ def exec_migration(conn, direction)
'Try removing disable_ddl_transaction! from your migration.'
end

set_statement_timeout_at_least_at(conn, min_timeout)
SetMinimumStatementTimeout.new(conn, self).call(min_timeout)

super
end

def set_statement_timeout_at_least_at(conn, min_timeout)
current_timeout = get_timeout(conn)
if in_ms(min_timeout) > in_ms(current_timeout)
set_timeout(conn, min_timeout)
say "set statement_timeout to #{min_timeout} (was #{current_timeout} before)"
else
say "ignore set statement_timeout to #{min_timeout}: it would be lower than current value #{current_timeout}"
end
end

def set_timeout(conn, timeout)
conn.execute("SET LOCAL statement_timeout = '#{timeout}'")
end

def get_timeout(conn)
conn.execute('SHOW statement_timeout').first['statement_timeout']
end

def in_ms(timeout)
case timeout
when Integer
timeout
when /\A\d+(ms)?\z/
timeout.to_i
when /\A\d+s\z/
timeout.to_i * 1000
when /\A\d+min\z/
timeout.to_i * 1000 * 60
when /\A\d+h\z/
timeout.to_i * 1000 * 60 * 60
else
raise "Unrecognized statement timeout duration #{timeout.inspect}"
end
end
end
end

0 comments on commit 7244ce3

Please sign in to comment.