Commit f21e655b authored by Gabriel Mazetto's avatar Gabriel Mazetto

disable_statement_timeout doesn't require any argument anymore

it will decide the method for disable statement_timeout upon
per transaction or per session, based on how it's called.

When calling with a block, block will be executed and it will use
session based statement_timeout, otherwise will default to existing
behavior.
parent f6d47d0d
...@@ -106,7 +106,7 @@ class ProjectForeignKeysWithCascadingDeletes < ActiveRecord::Migration ...@@ -106,7 +106,7 @@ class ProjectForeignKeysWithCascadingDeletes < ActiveRecord::Migration
# Disables statement timeouts for the current connection. This is # Disables statement timeouts for the current connection. This is
# necessary as removing of orphaned data might otherwise exceed the # necessary as removing of orphaned data might otherwise exceed the
# statement timeout. # statement timeout.
disable_statement_timeout(transaction: false) do disable_statement_timeout do
remove_orphans(*queue.pop) until queue.empty? remove_orphans(*queue.pop) until queue.empty?
steal_from_queues(queues - [queue]) steal_from_queues(queues - [queue])
......
...@@ -25,7 +25,7 @@ class AddLowerPathIndexToRedirectRoutes < ActiveRecord::Migration ...@@ -25,7 +25,7 @@ class AddLowerPathIndexToRedirectRoutes < ActiveRecord::Migration
# trivial to write a query that checks for an index. BUT there is a # trivial to write a query that checks for an index. BUT there is a
# convenient `IF EXISTS` parameter for `DROP INDEX`. # convenient `IF EXISTS` parameter for `DROP INDEX`.
if supports_drop_index_concurrently? if supports_drop_index_concurrently?
disable_statement_timeout(transaction: false) do disable_statement_timeout do
execute "DROP INDEX CONCURRENTLY IF EXISTS #{INDEX_NAME};" execute "DROP INDEX CONCURRENTLY IF EXISTS #{INDEX_NAME};"
end end
else else
......
...@@ -8,7 +8,7 @@ class AddIndexOnNamespacesLowerName < ActiveRecord::Migration ...@@ -8,7 +8,7 @@ class AddIndexOnNamespacesLowerName < ActiveRecord::Migration
def up def up
return unless Gitlab::Database.postgresql? return unless Gitlab::Database.postgresql?
disable_statement_timeout(transaction: false) do disable_statement_timeout do
if Gitlab::Database.version.to_f >= 9.5 if Gitlab::Database.version.to_f >= 9.5
# Allow us to hot-patch the index manually ahead of the migration # Allow us to hot-patch the index manually ahead of the migration
execute "CREATE INDEX CONCURRENTLY IF NOT EXISTS #{INDEX_NAME} ON namespaces (lower(name));" execute "CREATE INDEX CONCURRENTLY IF NOT EXISTS #{INDEX_NAME} ON namespaces (lower(name));"
...@@ -21,7 +21,7 @@ class AddIndexOnNamespacesLowerName < ActiveRecord::Migration ...@@ -21,7 +21,7 @@ class AddIndexOnNamespacesLowerName < ActiveRecord::Migration
def down def down
return unless Gitlab::Database.postgresql? return unless Gitlab::Database.postgresql?
disable_statement_timeout(transaction: false) do disable_statement_timeout do
if Gitlab::Database.version.to_f >= 9.2 if Gitlab::Database.version.to_f >= 9.2
execute "DROP INDEX CONCURRENTLY IF EXISTS #{INDEX_NAME};" execute "DROP INDEX CONCURRENTLY IF EXISTS #{INDEX_NAME};"
else else
......
...@@ -18,7 +18,7 @@ class ReworkRedirectRoutesIndexes < ActiveRecord::Migration ...@@ -18,7 +18,7 @@ class ReworkRedirectRoutesIndexes < ActiveRecord::Migration
OLD_INDEX_NAME_PATH_LOWER = "index_on_redirect_routes_lower_path" OLD_INDEX_NAME_PATH_LOWER = "index_on_redirect_routes_lower_path"
def up def up
disable_statement_timeout(transaction: false) do disable_statement_timeout do
# this is a plain btree on a single boolean column. It'll never be # this is a plain btree on a single boolean column. It'll never be
# selective enough to be valuable. This class is called by # selective enough to be valuable. This class is called by
# setup_postgresql.rake so it needs to be able to handle this # setup_postgresql.rake so it needs to be able to handle this
...@@ -29,7 +29,7 @@ class ReworkRedirectRoutesIndexes < ActiveRecord::Migration ...@@ -29,7 +29,7 @@ class ReworkRedirectRoutesIndexes < ActiveRecord::Migration
# If we're on MySQL then the existing index on path is ok. But on # If we're on MySQL then the existing index on path is ok. But on
# Postgres we need to clean things up: # Postgres we need to clean things up:
return unless Gitlab::Database.postgresql? break unless Gitlab::Database.postgresql?
if_not_exists = Gitlab::Database.version.to_f >= 9.5 ? "IF NOT EXISTS" : "" if_not_exists = Gitlab::Database.version.to_f >= 9.5 ? "IF NOT EXISTS" : ""
...@@ -52,10 +52,10 @@ class ReworkRedirectRoutesIndexes < ActiveRecord::Migration ...@@ -52,10 +52,10 @@ class ReworkRedirectRoutesIndexes < ActiveRecord::Migration
end end
def down def down
disable_statement_timeout(transaction: false) do disable_statement_timeout do
add_concurrent_index(:redirect_routes, :permanent) add_concurrent_index(:redirect_routes, :permanent)
return unless Gitlab::Database.postgresql? break unless Gitlab::Database.postgresql?
execute("CREATE INDEX CONCURRENTLY #{OLD_INDEX_NAME_PATH_TPOPS} ON redirect_routes (path varchar_pattern_ops);") execute("CREATE INDEX CONCURRENTLY #{OLD_INDEX_NAME_PATH_TPOPS} ON redirect_routes (path varchar_pattern_ops);")
execute("CREATE INDEX CONCURRENTLY #{OLD_INDEX_NAME_PATH_LOWER} ON redirect_routes (LOWER(path));") execute("CREATE INDEX CONCURRENTLY #{OLD_INDEX_NAME_PATH_LOWER} ON redirect_routes (LOWER(path));")
......
...@@ -13,7 +13,7 @@ class CreateProjectCiCdSettings < ActiveRecord::Migration ...@@ -13,7 +13,7 @@ class CreateProjectCiCdSettings < ActiveRecord::Migration
end end
end end
disable_statement_timeout(transaction: false) do disable_statement_timeout do
# This particular INSERT will take between 10 and 20 seconds. # This particular INSERT will take between 10 and 20 seconds.
execute 'INSERT INTO project_ci_cd_settings (project_id) SELECT id FROM projects' execute 'INSERT INTO project_ci_cd_settings (project_id) SELECT id FROM projects'
......
...@@ -14,7 +14,7 @@ class CleanupBuildStageMigration < ActiveRecord::Migration ...@@ -14,7 +14,7 @@ class CleanupBuildStageMigration < ActiveRecord::Migration
end end
def up def up
disable_statement_timeout(transaction: false) do disable_statement_timeout do
## ##
# We steal from the background migrations queue to catch up with the # We steal from the background migrations queue to catch up with the
# scheduled migrations set. # scheduled migrations set.
...@@ -55,7 +55,7 @@ class CleanupBuildStageMigration < ActiveRecord::Migration ...@@ -55,7 +55,7 @@ class CleanupBuildStageMigration < ActiveRecord::Migration
def down def down
if index_exists_by_name?(:ci_builds, TMP_INDEX) if index_exists_by_name?(:ci_builds, TMP_INDEX)
disable_statement_timeout(transaction: false) do disable_statement_timeout do
remove_concurrent_index_by_name(:ci_builds, TMP_INDEX) remove_concurrent_index_by_name(:ci_builds, TMP_INDEX)
end end
end end
......
...@@ -13,7 +13,7 @@ class ProjectNameLowerIndex < ActiveRecord::Migration ...@@ -13,7 +13,7 @@ class ProjectNameLowerIndex < ActiveRecord::Migration
def up def up
return unless Gitlab::Database.postgresql? return unless Gitlab::Database.postgresql?
disable_statement_timeout(transaction: false) do disable_statement_timeout do
execute "CREATE INDEX CONCURRENTLY #{INDEX_NAME} ON projects (LOWER(name))" execute "CREATE INDEX CONCURRENTLY #{INDEX_NAME} ON projects (LOWER(name))"
end end
end end
...@@ -21,7 +21,7 @@ class ProjectNameLowerIndex < ActiveRecord::Migration ...@@ -21,7 +21,7 @@ class ProjectNameLowerIndex < ActiveRecord::Migration
def down def down
return unless Gitlab::Database.postgresql? return unless Gitlab::Database.postgresql?
disable_statement_timeout(transaction: false) do disable_statement_timeout do
if supports_drop_index_concurrently? if supports_drop_index_concurrently?
execute "DROP INDEX CONCURRENTLY IF EXISTS #{INDEX_NAME}" execute "DROP INDEX CONCURRENTLY IF EXISTS #{INDEX_NAME}"
else else
......
...@@ -28,16 +28,16 @@ class RemoveOrphanedRoutes < ActiveRecord::Migration ...@@ -28,16 +28,16 @@ class RemoveOrphanedRoutes < ActiveRecord::Migration
# which is pretty close to our 15 second statement timeout. To ensure a # which is pretty close to our 15 second statement timeout. To ensure a
# smooth deployment procedure we disable the statement timeouts for this # smooth deployment procedure we disable the statement timeouts for this
# migration, just in case. # migration, just in case.
disable_statement_timeout disable_statement_timeout do
# On GitLab.com there are around 4000 orphaned project routes, and around
# On GitLab.com there are around 4000 orphaned project routes, and around # 150 orphaned namespace routes.
# 150 orphaned namespace routes. [
[ Route.orphaned_project_routes,
Route.orphaned_project_routes, Route.orphaned_namespace_routes
Route.orphaned_namespace_routes ].each do |relation|
].each do |relation| relation.each_batch(of: 1_000) do |batch|
relation.each_batch(of: 1_000) do |batch| batch.delete_all
batch.delete_all end
end end
end end
end end
......
...@@ -29,7 +29,7 @@ class CompositePrimaryKeysMigration < ActiveRecord::Migration ...@@ -29,7 +29,7 @@ class CompositePrimaryKeysMigration < ActiveRecord::Migration
def up def up
return unless Gitlab::Database.postgresql? return unless Gitlab::Database.postgresql?
disable_statement_timeout(transaction: false) do disable_statement_timeout do
TABLES.each do |index| TABLES.each do |index|
add_primary_key(index) add_primary_key(index)
end end
...@@ -39,7 +39,7 @@ class CompositePrimaryKeysMigration < ActiveRecord::Migration ...@@ -39,7 +39,7 @@ class CompositePrimaryKeysMigration < ActiveRecord::Migration
def down def down
return unless Gitlab::Database.postgresql? return unless Gitlab::Database.postgresql?
disable_statement_timeout(transaction: false) do disable_statement_timeout do
TABLES.each do |index| TABLES.each do |index|
remove_primary_key(index) remove_primary_key(index)
end end
......
...@@ -8,7 +8,7 @@ class EnableAutoCancelPendingPipelinesForAll < ActiveRecord::Migration ...@@ -8,7 +8,7 @@ class EnableAutoCancelPendingPipelinesForAll < ActiveRecord::Migration
DOWNTIME = false DOWNTIME = false
def up def up
disable_statement_timeout(transaction: false) do disable_statement_timeout do
update_column_in_batches(:projects, :auto_cancel_pending_pipelines, 1) update_column_in_batches(:projects, :auto_cancel_pending_pipelines, 1)
end end
end end
......
...@@ -10,7 +10,7 @@ class UpdateRetriedForCiBuild < ActiveRecord::Migration ...@@ -10,7 +10,7 @@ class UpdateRetriedForCiBuild < ActiveRecord::Migration
if Gitlab::Database.mysql? if Gitlab::Database.mysql?
up_mysql up_mysql
else else
disable_statement_timeout(transaction: false) do disable_statement_timeout do
up_postgres up_postgres
end end
end end
......
...@@ -10,7 +10,7 @@ class AddHeadPipelineForEachMergeRequest < ActiveRecord::Migration ...@@ -10,7 +10,7 @@ class AddHeadPipelineForEachMergeRequest < ActiveRecord::Migration
pipelines = Arel::Table.new(:ci_pipelines) pipelines = Arel::Table.new(:ci_pipelines)
merge_requests = Arel::Table.new(:merge_requests) merge_requests = Arel::Table.new(:merge_requests)
disable_statement_timeout(transaction: false) do disable_statement_timeout do
head_id = pipelines head_id = pipelines
.project(Arel::Nodes::NamedFunction.new('max', [pipelines[:id]])) .project(Arel::Nodes::NamedFunction.new('max', [pipelines[:id]]))
.from(pipelines) .from(pipelines)
......
...@@ -87,7 +87,7 @@ class RenameAllReservedPathsAgain < ActiveRecord::Migration ...@@ -87,7 +87,7 @@ class RenameAllReservedPathsAgain < ActiveRecord::Migration
].freeze ].freeze
def up def up
disable_statement_timeout(transaction: false) do disable_statement_timeout do
TOP_LEVEL_ROUTES.each { |route| rename_root_paths(route) } TOP_LEVEL_ROUTES.each { |route| rename_root_paths(route) }
PROJECT_WILDCARD_ROUTES.each { |route| rename_wildcard_paths(route) } PROJECT_WILDCARD_ROUTES.each { |route| rename_wildcard_paths(route) }
GROUP_ROUTES.each { |route| rename_child_paths(route) } GROUP_ROUTES.each { |route| rename_child_paths(route) }
...@@ -95,7 +95,7 @@ class RenameAllReservedPathsAgain < ActiveRecord::Migration ...@@ -95,7 +95,7 @@ class RenameAllReservedPathsAgain < ActiveRecord::Migration
end end
def down def down
disable_statement_timeout(transaction: false) do disable_statement_timeout do
revert_renames revert_renames
end end
end end
......
...@@ -6,7 +6,7 @@ class MigratePipelineStages < ActiveRecord::Migration ...@@ -6,7 +6,7 @@ class MigratePipelineStages < ActiveRecord::Migration
disable_ddl_transaction! disable_ddl_transaction!
def up def up
disable_statement_timeout(transaction: false) do disable_statement_timeout do
execute <<-SQL.strip_heredoc execute <<-SQL.strip_heredoc
INSERT INTO ci_stages (project_id, pipeline_id, name) INSERT INTO ci_stages (project_id, pipeline_id, name)
SELECT project_id, commit_id, stage FROM ci_builds SELECT project_id, commit_id, stage FROM ci_builds
......
...@@ -13,7 +13,7 @@ class MigrateBuildStageReferenceAgain < ActiveRecord::Migration ...@@ -13,7 +13,7 @@ class MigrateBuildStageReferenceAgain < ActiveRecord::Migration
AND ci_stages.name = ci_builds.stage) AND ci_stages.name = ci_builds.stage)
SQL SQL
disable_statement_timeout(transaction: false) do disable_statement_timeout do
update_column_in_batches(:ci_builds, :stage_id, stage_id) do |table, query| update_column_in_batches(:ci_builds, :stage_id, stage_id) do |table, query|
query.where(table[:stage_id].eq(nil)) query.where(table[:stage_id].eq(nil))
end end
...@@ -21,7 +21,7 @@ class MigrateBuildStageReferenceAgain < ActiveRecord::Migration ...@@ -21,7 +21,7 @@ class MigrateBuildStageReferenceAgain < ActiveRecord::Migration
end end
def down def down
disable_statement_timeout(transaction: false) do disable_statement_timeout do
update_column_in_batches(:ci_builds, :stage_id, nil) update_column_in_batches(:ci_builds, :stage_id, nil)
end end
end end
......
...@@ -26,8 +26,7 @@ class MigrateStagesStatuses < ActiveRecord::Migration ...@@ -26,8 +26,7 @@ class MigrateStagesStatuses < ActiveRecord::Migration
end end
def down def down
disable_statement_timeout(transaction: false) do disable_statement_timeout do
# rubocop:disable Migration/UpdateLargeTable # rubocop:disable Migration/UpdateLargeTable
update_column_in_batches(:ci_stages, :status, nil) update_column_in_batches(:ci_stages, :status, nil)
end end
......
...@@ -78,7 +78,7 @@ class RemoveSoftRemovedObjects < ActiveRecord::Migration ...@@ -78,7 +78,7 @@ class RemoveSoftRemovedObjects < ActiveRecord::Migration
MODELS = [Issue, MergeRequest, CiPipelineSchedule, CiTrigger].freeze MODELS = [Issue, MergeRequest, CiPipelineSchedule, CiTrigger].freeze
def up def up
disable_statement_timeout(transaction: false) do disable_statement_timeout do
remove_personal_routes remove_personal_routes
remove_personal_namespaces remove_personal_namespaces
remove_group_namespaces remove_group_namespaces
......
...@@ -38,7 +38,7 @@ class RemoveRedundantPipelineStages < ActiveRecord::Migration ...@@ -38,7 +38,7 @@ class RemoveRedundantPipelineStages < ActiveRecord::Migration
end end
def remove_redundant_pipeline_stages! def remove_redundant_pipeline_stages!
disable_statement_timeout(transaction: false) do disable_statement_timeout do
redundant_stages_ids = <<~SQL redundant_stages_ids = <<~SQL
SELECT id FROM ci_stages WHERE (pipeline_id, name) IN ( SELECT id FROM ci_stages WHERE (pipeline_id, name) IN (
SELECT pipeline_id, name FROM ci_stages SELECT pipeline_id, name FROM ci_stages
......
...@@ -15,7 +15,7 @@ class RemovePermanentFromRedirectRoutes < ActiveRecord::Migration ...@@ -15,7 +15,7 @@ class RemovePermanentFromRedirectRoutes < ActiveRecord::Migration
# ReworkRedirectRoutesIndexes: # ReworkRedirectRoutesIndexes:
# https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/16211 # https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/16211
if Gitlab::Database.postgresql? if Gitlab::Database.postgresql?
disable_statement_timeout(transaction: false) do disable_statement_timeout do
execute "DROP INDEX CONCURRENTLY IF EXISTS #{INDEX_NAME_PERM};" execute "DROP INDEX CONCURRENTLY IF EXISTS #{INDEX_NAME_PERM};"
execute "DROP INDEX CONCURRENTLY IF EXISTS #{INDEX_NAME_TEMP};" execute "DROP INDEX CONCURRENTLY IF EXISTS #{INDEX_NAME_TEMP};"
end end
...@@ -28,7 +28,7 @@ class RemovePermanentFromRedirectRoutes < ActiveRecord::Migration ...@@ -28,7 +28,7 @@ class RemovePermanentFromRedirectRoutes < ActiveRecord::Migration
add_column(:redirect_routes, :permanent, :boolean) add_column(:redirect_routes, :permanent, :boolean)
if Gitlab::Database.postgresql? if Gitlab::Database.postgresql?
disable_statement_timeout(transaction: false) do disable_statement_timeout do
execute("CREATE INDEX CONCURRENTLY #{INDEX_NAME_PERM} ON redirect_routes (lower(path) varchar_pattern_ops) where (permanent);") execute("CREATE INDEX CONCURRENTLY #{INDEX_NAME_PERM} ON redirect_routes (lower(path) varchar_pattern_ops) where (permanent);")
execute("CREATE INDEX CONCURRENTLY #{INDEX_NAME_TEMP} ON redirect_routes (lower(path) varchar_pattern_ops) where (not permanent or permanent is null) ;") execute("CREATE INDEX CONCURRENTLY #{INDEX_NAME_TEMP} ON redirect_routes (lower(path) varchar_pattern_ops) where (not permanent or permanent is null) ;")
end end
......
...@@ -20,7 +20,7 @@ class AddPathIndexToRedirectRoutes < ActiveRecord::Migration ...@@ -20,7 +20,7 @@ class AddPathIndexToRedirectRoutes < ActiveRecord::Migration
def up def up
return unless Gitlab::Database.postgresql? return unless Gitlab::Database.postgresql?
disable_statement_timeout(transaction: false) do disable_statement_timeout do
unless index_exists_by_name?(:redirect_routes, INDEX_NAME) unless index_exists_by_name?(:redirect_routes, INDEX_NAME)
execute("CREATE UNIQUE INDEX CONCURRENTLY #{INDEX_NAME} ON redirect_routes (lower(path) varchar_pattern_ops);") execute("CREATE UNIQUE INDEX CONCURRENTLY #{INDEX_NAME} ON redirect_routes (lower(path) varchar_pattern_ops);")
end end
......
...@@ -17,7 +17,7 @@ class RescheduleBuildsStagesMigration < ActiveRecord::Migration ...@@ -17,7 +17,7 @@ class RescheduleBuildsStagesMigration < ActiveRecord::Migration
end end
def up def up
disable_statement_timeout(transaction: false) do disable_statement_timeout do
Build.where('stage_id IS NULL').tap do |relation| Build.where('stage_id IS NULL').tap do |relation|
queue_background_migration_jobs_by_range_at_intervals(relation, queue_background_migration_jobs_by_range_at_intervals(relation,
MIGRATION, MIGRATION,
......
...@@ -13,7 +13,7 @@ class ScheduleStagesIndexMigration < ActiveRecord::Migration ...@@ -13,7 +13,7 @@ class ScheduleStagesIndexMigration < ActiveRecord::Migration
end end
def up def up
disable_statement_timeout(transaction: false) do disable_statement_timeout do
Stage.all.tap do |relation| Stage.all.tap do |relation|
queue_background_migration_jobs_by_range_at_intervals(relation, queue_background_migration_jobs_by_range_at_intervals(relation,
MIGRATION, MIGRATION,
......
...@@ -12,7 +12,7 @@ class CleanupStagesPositionMigration < ActiveRecord::Migration ...@@ -12,7 +12,7 @@ class CleanupStagesPositionMigration < ActiveRecord::Migration
end end
def up def up
disable_statement_timeout(transaction: false) do disable_statement_timeout do
Gitlab::BackgroundMigration.steal('MigrateStageIndex') Gitlab::BackgroundMigration.steal('MigrateStageIndex')
unless index_exists_by_name?(:ci_stages, TMP_INDEX_NAME) unless index_exists_by_name?(:ci_stages, TMP_INDEX_NAME)
...@@ -37,7 +37,7 @@ class CleanupStagesPositionMigration < ActiveRecord::Migration ...@@ -37,7 +37,7 @@ class CleanupStagesPositionMigration < ActiveRecord::Migration
def down def down
if index_exists_by_name?(:ci_stages, TMP_INDEX_NAME) if index_exists_by_name?(:ci_stages, TMP_INDEX_NAME)
disable_statement_timeout(transaction: false) do disable_statement_timeout do
remove_concurrent_index_by_name(:ci_stages, TMP_INDEX_NAME) remove_concurrent_index_by_name(:ci_stages, TMP_INDEX_NAME)
end end
end end
......
...@@ -65,7 +65,7 @@ module Gitlab ...@@ -65,7 +65,7 @@ module Gitlab
return return
end end
disable_statement_timeout(transaction: false) do disable_statement_timeout do
add_index(table_name, column_name, options) add_index(table_name, column_name, options)
end end
end end
...@@ -95,7 +95,7 @@ module Gitlab ...@@ -95,7 +95,7 @@ module Gitlab
return return
end end
disable_statement_timeout(transaction: false) do disable_statement_timeout do
remove_index(table_name, options.merge({ column: column_name })) remove_index(table_name, options.merge({ column: column_name }))
end end
end end
...@@ -125,7 +125,7 @@ module Gitlab ...@@ -125,7 +125,7 @@ module Gitlab
return return
end end
disable_statement_timeout(transaction: false) do disable_statement_timeout do
remove_index(table_name, options.merge({ name: index_name })) remove_index(table_name, options.merge({ name: index_name }))
end end
end end
...@@ -200,7 +200,7 @@ module Gitlab ...@@ -200,7 +200,7 @@ module Gitlab
# while running. # while running.
# #
# Note this is a no-op in case the constraint is VALID already # Note this is a no-op in case the constraint is VALID already
disable_statement_timeout(transaction: false) do disable_statement_timeout do
execute("ALTER TABLE #{source} VALIDATE CONSTRAINT #{key_name};") execute("ALTER TABLE #{source} VALIDATE CONSTRAINT #{key_name};")
end end
end end
...@@ -233,13 +233,11 @@ module Gitlab ...@@ -233,13 +233,11 @@ module Gitlab
# - Per transaction (this is the preferred and default mode) # - Per transaction (this is the preferred and default mode)
# - Per connection (requires a cleanup after the execution) # - Per connection (requires a cleanup after the execution)
# #
# When using a per connection disable statement, code must be inside a block # When using a per connection disable statement, code must be inside
# so we can automatically `RESET ALL` after it has executed otherwise the statement # a block so we can automatically execute `RESET ALL` after block finishes
# will still be disabled until connection is dropped or `RESET ALL` is executed # otherwise the statement will still be disabled until connection is dropped
# # or `RESET ALL` is executed
# - +transaction:+ true to disable for current transaction only *(default)* def disable_statement_timeout
# - +transaction:+ false to disable for current session (requires block)
def disable_statement_timeout(transaction: true)
# bypass disabled_statement logic when not using postgres, but still execute block when one is given # bypass disabled_statement logic when not using postgres, but still execute block when one is given
unless Database.postgresql? unless Database.postgresql?
if block_given? if block_given?
...@@ -249,26 +247,27 @@ module Gitlab ...@@ -249,26 +247,27 @@ module Gitlab
return return
end end
if transaction if block_given?
unless transaction_open? begin
raise 'disable_statement_timeout() cannot be run without a transaction, ' \ execute('SET statement_timeout TO 0')
'use it inside a transaction block. Alternatively you can use: ' \
'disable_statement_timeout(transaction: false) { #code here } to make sure ' \
'statement_timeout is reset after the block execution is finished.'
end
execute('SET LOCAL statement_timeout TO 0') yield
else ensure
unless block_given? execute('RESET ALL')
raise ArgumentError, 'disable_statement_timeout(transaction: false) requires a block encapsulating' \
'code that will be executed with the statement_timeout disabled.'
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:
execute('SET statement_timeout TO 0') disable_statement_timeout { # code that requires disabled statement here }
yield This will make sure statement_timeout is disabled before and reset after the block execution is finished.
ERROR
end
execute('RESET ALL') execute('SET LOCAL statement_timeout TO 0')
end end
end end
...@@ -411,7 +410,7 @@ module Gitlab ...@@ -411,7 +410,7 @@ module Gitlab
'in the body of your migration class' 'in the body of your migration class'
end end
disable_statement_timeout(transaction: false) do disable_statement_timeout do
transaction do transaction do
if limit if limit
add_column(table, column, type, default: nil, limit: limit) add_column(table, column, type, default: nil, limit: limit)
......
...@@ -296,52 +296,43 @@ describe Gitlab::Database::MigrationHelpers do ...@@ -296,52 +296,43 @@ describe Gitlab::Database::MigrationHelpers do
describe '#disable_statement_timeout' do describe '#disable_statement_timeout' do
context 'using PostgreSQL' do context 'using PostgreSQL' do
context 'with transaction: true' do it 'disables statement timeouts to current transaction only' do
it 'disables statement timeouts to current transaction only' do expect(Gitlab::Database).to receive(:postgresql?).and_return(true)
expect(Gitlab::Database).to receive(:postgresql?).and_return(true)
expect(model).to receive(:execute).with('SET LOCAL statement_timeout TO 0')
model.disable_statement_timeout expect(model).to receive(:execute).with('SET LOCAL statement_timeout TO 0')
end
# this specs runs without an enclosing transaction (:delete truncation method for db_cleaner) model.disable_statement_timeout
context 'with real environment', :postgresql, :delete do end
before do
model.execute("SET statement_timeout TO '20000'")
end
after do # this specs runs without an enclosing transaction (:delete truncation method for db_cleaner)
model.execute('RESET ALL') context 'with real environment', :postgresql, :delete do
end before do
model.execute("SET statement_timeout TO '20000'")
end
it 'defines statement to 0 only for current transaction' do after do
expect(model.execute('SHOW statement_timeout').first['statement_timeout']).to eq('20s') model.execute('RESET ALL')
end
model.connection.transaction do it 'defines statement to 0 only for current transaction' do
model.disable_statement_timeout expect(model.execute('SHOW statement_timeout').first['statement_timeout']).to eq('20s')
expect(model.execute('SHOW statement_timeout').first['statement_timeout']).to eq('0')
end
expect(model.execute('SHOW statement_timeout').first['statement_timeout']).to eq('20s') model.connection.transaction do
model.disable_statement_timeout
expect(model.execute('SHOW statement_timeout').first['statement_timeout']).to eq('0')
end end
expect(model.execute('SHOW statement_timeout').first['statement_timeout']).to eq('20s')
end end
end end
context 'with transaction: false' do context 'when passing a blocks' do
it 'disables statement timeouts on session level' do it 'disables statement timeouts on session level and executes the block' do
expect(Gitlab::Database).to receive(:postgresql?).and_return(true) expect(Gitlab::Database).to receive(:postgresql?).and_return(true)
expect(model).to receive(:execute).with('SET statement_timeout TO 0') expect(model).to receive(:execute).with('SET statement_timeout TO 0')
expect(model).to receive(:execute).with('RESET ALL') expect(model).to receive(:execute).with('RESET ALL')
model.disable_statement_timeout(transaction: false) do expect { |block| model.disable_statement_timeout(&block) }.to yield_control
# no-op
end
end
it 'raises error when no block is given' do
expect(Gitlab::Database).to receive(:postgresql?).and_return(true)
expect { model.disable_statement_timeout(transaction: false) }.to raise_error(ArgumentError)
end end
# this specs runs without an enclosing transaction (:delete truncation method for db_cleaner) # this specs runs without an enclosing transaction (:delete truncation method for db_cleaner)
...@@ -354,10 +345,10 @@ describe Gitlab::Database::MigrationHelpers do ...@@ -354,10 +345,10 @@ describe Gitlab::Database::MigrationHelpers do
model.execute('RESET ALL') model.execute('RESET ALL')
end end
it 'defines statement to 0 for any code run inside block' do it 'defines statement to 0 for any code run inside the block' do
expect(model.execute('SHOW statement_timeout').first['statement_timeout']).to eq('20s') expect(model.execute('SHOW statement_timeout').first['statement_timeout']).to eq('20s')
model.disable_statement_timeout(transaction: false) do model.disable_statement_timeout do
model.connection.transaction do model.connection.transaction do
expect(model.execute('SHOW statement_timeout').first['statement_timeout']).to eq('0') expect(model.execute('SHOW statement_timeout').first['statement_timeout']).to eq('0')
end end
...@@ -370,23 +361,21 @@ describe Gitlab::Database::MigrationHelpers do ...@@ -370,23 +361,21 @@ describe Gitlab::Database::MigrationHelpers do
end end
context 'using MySQL' do context 'using MySQL' do
context 'with transaction: true' do it 'does nothing' do
it 'does nothing' do expect(Gitlab::Database).to receive(:postgresql?).and_return(false)
expect(Gitlab::Database).to receive(:postgresql?).and_return(false)
expect(model).not_to receive(:execute) expect(model).not_to receive(:execute)
model.disable_statement_timeout model.disable_statement_timeout
end
end end
context 'with transaction: false' do context 'when passing a blocks' do
it 'executes yielded code' do it 'executes the block of code' do
expect(Gitlab::Database).to receive(:postgresql?).and_return(false) expect(Gitlab::Database).to receive(:postgresql?).and_return(false)
expect(model).not_to receive(:execute) expect(model).not_to receive(:execute)
expect { |block| model.disable_statement_timeout(transaction: false, &block) }.to yield_control expect { |block| model.disable_statement_timeout(&block) }.to yield_control
end end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment