Commit dc30afec authored by pbair's avatar pbair

Remove default connection for WithLockRetries

Make the :connection argument for WithLockRetries, by removing the
default of ActiveRecord::Base. This prevents accidental use of the wrong
connection once we begin using multiple databases.
parent a9c82335
...@@ -19,7 +19,6 @@ Database/MultipleDatabases: ...@@ -19,7 +19,6 @@ Database/MultipleDatabases:
- lib/gitlab/database/migrations/observers/query_log.rb - lib/gitlab/database/migrations/observers/query_log.rb
- lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb - lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb
- lib/gitlab/database.rb - lib/gitlab/database.rb
- lib/gitlab/database/with_lock_retries.rb
- lib/gitlab/gitlab_import/importer.rb - lib/gitlab/gitlab_import/importer.rb
- lib/gitlab/health_checks/db_check.rb - lib/gitlab/health_checks/db_check.rb
- lib/gitlab/import_export/base/relation_factory.rb - lib/gitlab/import_export/base/relation_factory.rb
......
...@@ -5,7 +5,7 @@ class CreatePackagesHelmFileMetadata < ActiveRecord::Migration[6.0] ...@@ -5,7 +5,7 @@ class CreatePackagesHelmFileMetadata < ActiveRecord::Migration[6.0]
DOWNTIME = false DOWNTIME = false
def change def up
create_table_with_constraints :packages_helm_file_metadata, id: false do |t| create_table_with_constraints :packages_helm_file_metadata, id: false do |t|
t.timestamps_with_timezone t.timestamps_with_timezone
t.references :package_file, primary_key: true, index: false, default: nil, null: false, foreign_key: { to_table: :packages_package_files, on_delete: :cascade }, type: :bigint t.references :package_file, primary_key: true, index: false, default: nil, null: false, foreign_key: { to_table: :packages_package_files, on_delete: :cascade }, type: :bigint
...@@ -17,4 +17,10 @@ class CreatePackagesHelmFileMetadata < ActiveRecord::Migration[6.0] ...@@ -17,4 +17,10 @@ class CreatePackagesHelmFileMetadata < ActiveRecord::Migration[6.0]
t.index :channel t.index :channel
end end
end end
def down
with_lock_retries do
drop_table :packages_helm_file_metadata
end
end
end end
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
class CreateClustersIntegrationElasticstack < ActiveRecord::Migration[6.0] class CreateClustersIntegrationElasticstack < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
def change def up
create_table_with_constraints :clusters_integration_elasticstack, id: false do |t| create_table_with_constraints :clusters_integration_elasticstack, id: false do |t|
t.timestamps_with_timezone null: false t.timestamps_with_timezone null: false
t.references :cluster, primary_key: true, default: nil, index: false, foreign_key: { on_delete: :cascade } t.references :cluster, primary_key: true, default: nil, index: false, foreign_key: { on_delete: :cascade }
...@@ -12,4 +12,10 @@ class CreateClustersIntegrationElasticstack < ActiveRecord::Migration[6.0] ...@@ -12,4 +12,10 @@ class CreateClustersIntegrationElasticstack < ActiveRecord::Migration[6.0]
t.text_limit :chart_version, 10 t.text_limit :chart_version, 10
end end
end end
def down
with_lock_retries do
drop_table :clusters_integration_elasticstack
end
end
end end
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
class CreateDetachedPartitionsTable < ActiveRecord::Migration[6.1] class CreateDetachedPartitionsTable < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
def change def up
create_table_with_constraints :detached_partitions do |t| create_table_with_constraints :detached_partitions do |t|
t.timestamps_with_timezone null: false t.timestamps_with_timezone null: false
t.datetime_with_timezone :drop_after, null: false t.datetime_with_timezone :drop_after, null: false
...@@ -14,4 +14,10 @@ class CreateDetachedPartitionsTable < ActiveRecord::Migration[6.1] ...@@ -14,4 +14,10 @@ class CreateDetachedPartitionsTable < ActiveRecord::Migration[6.1]
t.text_limit :table_name, 63 t.text_limit :table_name, 63
end end
end end
def down
with_lock_retries do
drop_table :detached_partitions
end
end
end end
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
class CreatePostgresAsyncIndexesTable < ActiveRecord::Migration[6.1] class CreatePostgresAsyncIndexesTable < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
def change def up
create_table_with_constraints :postgres_async_indexes do |t| create_table_with_constraints :postgres_async_indexes do |t|
t.timestamps_with_timezone null: false t.timestamps_with_timezone null: false
...@@ -18,4 +18,10 @@ class CreatePostgresAsyncIndexesTable < ActiveRecord::Migration[6.1] ...@@ -18,4 +18,10 @@ class CreatePostgresAsyncIndexesTable < ActiveRecord::Migration[6.1]
t.index :name, unique: true t.index :name, unique: true
end end
end end
def down
with_lock_retries do
drop_table :postgres_async_indexes
end
end
end end
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
class CreateTopics < ActiveRecord::Migration[6.1] class CreateTopics < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
def change def up
create_table_with_constraints :topics do |t| create_table_with_constraints :topics do |t|
t.text :name, null: false t.text :name, null: false
t.text_limit :name, 255 t.text_limit :name, 255
...@@ -13,4 +13,10 @@ class CreateTopics < ActiveRecord::Migration[6.1] ...@@ -13,4 +13,10 @@ class CreateTopics < ActiveRecord::Migration[6.1]
t.timestamps_with_timezone t.timestamps_with_timezone
end end
end end
def down
with_lock_retries do
drop_table :topics
end
end
end end
...@@ -429,6 +429,7 @@ module Gitlab ...@@ -429,6 +429,7 @@ module Gitlab
def with_lock_retries(*args, **kwargs, &block) def with_lock_retries(*args, **kwargs, &block)
raise_on_exhaustion = !!kwargs.delete(:raise_on_exhaustion) raise_on_exhaustion = !!kwargs.delete(:raise_on_exhaustion)
merged_args = { merged_args = {
connection: connection,
klass: self.class, klass: self.class,
logger: Gitlab::BackgroundMigration::Logger, logger: Gitlab::BackgroundMigration::Logger,
allow_savepoints: true allow_savepoints: true
......
...@@ -9,6 +9,10 @@ module Gitlab ...@@ -9,6 +9,10 @@ module Gitlab
migration.class migration.class
end end
def migration_connection
migration.connection
end
def enable_lock_retries? def enable_lock_retries?
# regular AR migrations don't have this, # regular AR migrations don't have this,
# only ones inheriting from Gitlab::Database::Migration have # only ones inheriting from Gitlab::Database::Migration have
...@@ -24,6 +28,7 @@ module Gitlab ...@@ -24,6 +28,7 @@ module Gitlab
def ddl_transaction(migration, &block) def ddl_transaction(migration, &block)
if use_transaction?(migration) && migration.enable_lock_retries? if use_transaction?(migration) && migration.enable_lock_retries?
Gitlab::Database::WithLockRetries.new( Gitlab::Database::WithLockRetries.new(
connection: migration.migration_connection,
klass: migration.migration_class, klass: migration.migration_class,
logger: Gitlab::BackgroundMigration::Logger logger: Gitlab::BackgroundMigration::Logger
).run(raise_on_exhaustion: false, &block) ).run(raise_on_exhaustion: false, &block)
......
...@@ -73,6 +73,7 @@ module Gitlab ...@@ -73,6 +73,7 @@ module Gitlab
def with_lock_retries(&block) def with_lock_retries(&block)
Gitlab::Database::WithLockRetries.new( Gitlab::Database::WithLockRetries.new(
connection: connection,
klass: self.class, klass: self.class,
logger: Gitlab::BackgroundMigration::Logger logger: Gitlab::BackgroundMigration::Logger
).run(&block) ).run(&block)
......
...@@ -61,7 +61,7 @@ module Gitlab ...@@ -61,7 +61,7 @@ module Gitlab
[10.seconds, 10.minutes] [10.seconds, 10.minutes]
].freeze ].freeze
def initialize(logger: NULL_LOGGER, allow_savepoints: true, timing_configuration: DEFAULT_TIMING_CONFIGURATION, klass: nil, env: ENV, connection: ActiveRecord::Base.connection) def initialize(logger: NULL_LOGGER, allow_savepoints: true, timing_configuration: DEFAULT_TIMING_CONFIGURATION, klass: nil, env: ENV, connection:)
@logger = logger @logger = logger
@klass = klass @klass = klass
@allow_savepoints = allow_savepoints @allow_savepoints = allow_savepoints
......
...@@ -3,7 +3,8 @@ require 'spec_helper' ...@@ -3,7 +3,8 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::LockRetryMixin do RSpec.describe Gitlab::Database::Migrations::LockRetryMixin do
describe Gitlab::Database::Migrations::LockRetryMixin::ActiveRecordMigrationProxyLockRetries do describe Gitlab::Database::Migrations::LockRetryMixin::ActiveRecordMigrationProxyLockRetries do
let(:migration) { double } let(:connection) { ActiveRecord::Base.connection }
let(:migration) { double(connection: connection) }
let(:return_value) { double } let(:return_value) { double }
let(:class_def) do let(:class_def) do
Class.new do Class.new do
...@@ -40,6 +41,18 @@ RSpec.describe Gitlab::Database::Migrations::LockRetryMixin do ...@@ -40,6 +41,18 @@ RSpec.describe Gitlab::Database::Migrations::LockRetryMixin do
expect(result).to eq(return_value) expect(result).to eq(return_value)
end end
end end
describe '#migration_connection' do
subject { class_def.new(migration).migration_connection }
it 'retrieves actual migration connection from #migration' do
expect(migration).to receive(:connection).and_return(return_value)
result = subject
expect(result).to eq(return_value)
end
end
end end
describe Gitlab::Database::Migrations::LockRetryMixin::ActiveRecordMigratorLockRetries do describe Gitlab::Database::Migrations::LockRetryMixin::ActiveRecordMigratorLockRetries do
...@@ -96,7 +109,8 @@ RSpec.describe Gitlab::Database::Migrations::LockRetryMixin do ...@@ -96,7 +109,8 @@ RSpec.describe Gitlab::Database::Migrations::LockRetryMixin do
context 'with transactions enabled and lock retries enabled' do context 'with transactions enabled and lock retries enabled' do
let(:receiver) { double('receiver', use_transaction?: true)} let(:receiver) { double('receiver', use_transaction?: true)}
let(:migration) { double('migration', enable_lock_retries?: true) } let(:migration) { double('migration', migration_connection: connection, enable_lock_retries?: true) }
let(:connection) { ActiveRecord::Base.connection }
it 'calls super method' do it 'calls super method' do
p = proc { } p = proc { }
......
...@@ -5,7 +5,8 @@ require 'spec_helper' ...@@ -5,7 +5,8 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
let(:env) { {} } let(:env) { {} }
let(:logger) { Gitlab::Database::WithLockRetries::NULL_LOGGER } let(:logger) { Gitlab::Database::WithLockRetries::NULL_LOGGER }
let(:subject) { described_class.new(env: env, logger: logger, timing_configuration: timing_configuration) } let(:subject) { described_class.new(connection: connection, env: env, logger: logger, timing_configuration: timing_configuration) }
let(:connection) { ActiveRecord::Base.retrieve_connection }
let(:timing_configuration) do let(:timing_configuration) do
[ [
...@@ -67,7 +68,7 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do ...@@ -67,7 +68,7 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
WHERE t.relkind = 'r' AND l.mode = 'ExclusiveLock' AND t.relname = '#{Project.table_name}' WHERE t.relkind = 'r' AND l.mode = 'ExclusiveLock' AND t.relname = '#{Project.table_name}'
""" """
expect(ActiveRecord::Base.connection.execute(check_exclusive_lock_query).to_a).to be_present expect(connection.execute(check_exclusive_lock_query).to_a).to be_present
end end
end end
...@@ -96,8 +97,8 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do ...@@ -96,8 +97,8 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
lock_fiber.resume lock_fiber.resume
end end
ActiveRecord::Base.transaction do connection.transaction do
ActiveRecord::Base.connection.execute("LOCK TABLE #{Project.table_name} in exclusive mode") connection.execute("LOCK TABLE #{Project.table_name} in exclusive mode")
lock_acquired = true lock_acquired = true
end end
end end
...@@ -115,7 +116,7 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do ...@@ -115,7 +116,7 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
context 'setting the idle transaction timeout' do context 'setting the idle transaction timeout' do
context 'when there is no outer transaction: disable_ddl_transaction! is set in the migration' do context 'when there is no outer transaction: disable_ddl_transaction! is set in the migration' do
it 'does not disable the idle transaction timeout' do it 'does not disable the idle transaction timeout' do
allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false) allow(connection).to receive(:transaction_open?).and_return(false)
allow(subject).to receive(:run_block_with_lock_timeout).once.and_raise(ActiveRecord::LockWaitTimeout) allow(subject).to receive(:run_block_with_lock_timeout).once.and_raise(ActiveRecord::LockWaitTimeout)
allow(subject).to receive(:run_block_with_lock_timeout).once allow(subject).to receive(:run_block_with_lock_timeout).once
...@@ -127,7 +128,7 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do ...@@ -127,7 +128,7 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
context 'when there is outer transaction: disable_ddl_transaction! is not set in the migration' do context 'when there is outer transaction: disable_ddl_transaction! is not set in the migration' do
it 'disables the idle transaction timeout so the code can sleep and retry' do it 'disables the idle transaction timeout so the code can sleep and retry' do
allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(true) allow(connection).to receive(:transaction_open?).and_return(true)
n = 0 n = 0
allow(subject).to receive(:run_block_with_lock_timeout).twice do allow(subject).to receive(:run_block_with_lock_timeout).twice do
...@@ -184,8 +185,8 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do ...@@ -184,8 +185,8 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
subject.run(raise_on_exhaustion: true) do subject.run(raise_on_exhaustion: true) do
lock_attempts += 1 lock_attempts += 1
ActiveRecord::Base.transaction do connection.transaction do
ActiveRecord::Base.connection.execute("LOCK TABLE #{Project.table_name} in exclusive mode") connection.execute("LOCK TABLE #{Project.table_name} in exclusive mode")
lock_acquired = true lock_acquired = true
end end
end end
...@@ -199,11 +200,11 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do ...@@ -199,11 +200,11 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
context 'when statement timeout is reached' do context 'when statement timeout is reached' do
it 'raises StatementInvalid error' do it 'raises StatementInvalid error' do
lock_acquired = false lock_acquired = false
ActiveRecord::Base.connection.execute("SET statement_timeout='100ms'") connection.execute("SET statement_timeout='100ms'")
expect do expect do
subject.run do subject.run do
ActiveRecord::Base.connection.execute("SELECT 1 FROM pg_sleep(0.11)") # 110ms connection.execute("SELECT 1 FROM pg_sleep(0.11)") # 110ms
lock_acquired = true lock_acquired = true
end end
end.to raise_error(ActiveRecord::StatementInvalid) end.to raise_error(ActiveRecord::StatementInvalid)
...@@ -216,11 +217,11 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do ...@@ -216,11 +217,11 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
context 'restore local database variables' do context 'restore local database variables' do
it do it do
expect { subject.run {} }.not_to change { ActiveRecord::Base.connection.execute("SHOW lock_timeout").to_a } expect { subject.run {} }.not_to change { connection.execute("SHOW lock_timeout").to_a }
end end
it do it do
expect { subject.run {} }.not_to change { ActiveRecord::Base.connection.execute("SHOW idle_in_transaction_session_timeout").to_a } expect { subject.run {} }.not_to change { connection.execute("SHOW idle_in_transaction_session_timeout").to_a }
end end
end end
...@@ -228,8 +229,8 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do ...@@ -228,8 +229,8 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
let(:timing_configuration) { [[0.015.seconds, 0.025.seconds], [0.015.seconds, 0.025.seconds]] } # 15ms, 25ms let(:timing_configuration) { [[0.015.seconds, 0.025.seconds], [0.015.seconds, 0.025.seconds]] } # 15ms, 25ms
it 'executes `SET lock_timeout` using the configured timeout value in milliseconds' do it 'executes `SET lock_timeout` using the configured timeout value in milliseconds' do
expect(ActiveRecord::Base.connection).to receive(:execute).with('RESET idle_in_transaction_session_timeout; RESET lock_timeout').and_call_original expect(connection).to receive(:execute).with('RESET idle_in_transaction_session_timeout; RESET lock_timeout').and_call_original
expect(ActiveRecord::Base.connection).to receive(:execute).with("SET lock_timeout TO '15ms'").and_call_original expect(connection).to receive(:execute).with("SET lock_timeout TO '15ms'").and_call_original
subject.run { } subject.run { }
end end
......
...@@ -5,7 +5,7 @@ require 'spec_helper' ...@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::WithLockRetries do RSpec.describe Gitlab::Database::WithLockRetries do
let(:env) { {} } let(:env) { {} }
let(:logger) { Gitlab::Database::WithLockRetries::NULL_LOGGER } let(:logger) { Gitlab::Database::WithLockRetries::NULL_LOGGER }
let(:subject) { described_class.new(env: env, logger: logger, allow_savepoints: allow_savepoints, timing_configuration: timing_configuration) } let(:subject) { described_class.new(connection: connection, env: env, logger: logger, allow_savepoints: allow_savepoints, timing_configuration: timing_configuration) }
let(:allow_savepoints) { true } let(:allow_savepoints) { true }
let(:connection) { ActiveRecord::Base.retrieve_connection } let(:connection) { ActiveRecord::Base.retrieve_connection }
......
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