summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Bizon <grzesiek.bizon@gmail.com>2017-07-14 12:48:11 +0200
committerGrzegorz Bizon <grzesiek.bizon@gmail.com>2017-07-14 12:55:52 +0200
commit39b96f02dca3d6edac40b94bf003e6735c4c2524 (patch)
tree1bf0377a3e53fa95451a5f0d34a6de3a56035d90
parentbeffbc8aa2845d7a2859c269fd2c891cddb308e6 (diff)
downloadgitlab-ce-39b96f02dca3d6edac40b94bf003e6735c4c2524.tar.gz
Avoid race condition when stealing a background migration
We first pop a job from the Sidekiq queue / scheduled set and only if this has been successfully deleted we process the job. This makes it possible to minimize a possibility of a race condition happening.
-rw-r--r--lib/gitlab/background_migration.rb4
-rw-r--r--spec/lib/gitlab/background_migration_spec.rb10
2 files changed, 10 insertions, 4 deletions
diff --git a/lib/gitlab/background_migration.rb b/lib/gitlab/background_migration.rb
index e0325c0138e..73d2611e51f 100644
--- a/lib/gitlab/background_migration.rb
+++ b/lib/gitlab/background_migration.rb
@@ -19,9 +19,7 @@ module Gitlab
next unless job.queue == self.queue
next unless migration_class == steal_class
- perform(migration_class, migration_args)
-
- job.delete
+ perform(migration_class, migration_args) if job.delete
end
end
end
diff --git a/spec/lib/gitlab/background_migration_spec.rb b/spec/lib/gitlab/background_migration_spec.rb
index 2f3e7aba1f4..c12040cba14 100644
--- a/spec/lib/gitlab/background_migration_spec.rb
+++ b/spec/lib/gitlab/background_migration_spec.rb
@@ -23,13 +23,21 @@ describe Gitlab::BackgroundMigration do
end
it 'steals jobs from a queue' do
- expect(queue[0]).to receive(:delete)
+ expect(queue[0]).to receive(:delete).and_return(true)
expect(described_class).to receive(:perform).with('Foo', [10, 20])
described_class.steal('Foo')
end
+ it 'does not steal job that has already been taken' do
+ expect(queue[0]).to receive(:delete).and_return(false)
+
+ expect(described_class).not_to receive(:perform).with('Foo', [10, 20])
+
+ described_class.steal('Foo')
+ end
+
it 'does not steal jobs for a different migration' do
expect(described_class).not_to receive(:perform)