diff options
author | Rémy Coutable <remy@rymai.me> | 2018-01-08 13:06:49 +0000 |
---|---|---|
committer | Rémy Coutable <remy@rymai.me> | 2018-01-08 13:06:49 +0000 |
commit | 8ff0c9b15124a391bc2fc9059211d2b8d5373a2d (patch) | |
tree | 68338bf5810c4c00d08098b3d198e0acaa1025e7 /app/workers | |
parent | 93f30e2d3f654051adbf2271783382b3de53245d (diff) | |
parent | 7f30bb9c29bc1ff0c903a16bbf678db31c7408ec (diff) | |
download | gitlab-ce-8ff0c9b15124a391bc2fc9059211d2b8d5373a2d.tar.gz |
Merge branch 'delay-background-migrations' into 'master'
Run background migrations with a minimum interval
Closes #41624
See merge request gitlab-org/gitlab-ce!16230
Diffstat (limited to 'app/workers')
-rw-r--r-- | app/workers/background_migration_worker.rb | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/app/workers/background_migration_worker.rb b/app/workers/background_migration_worker.rb index aeb3bc019b9..376703f6319 100644 --- a/app/workers/background_migration_worker.rb +++ b/app/workers/background_migration_worker.rb @@ -1,10 +1,53 @@ class BackgroundMigrationWorker include ApplicationWorker + # The minimum amount of time between processing two jobs of the same migration + # class. + # + # This interval is set to 5 minutes so autovacuuming and other maintenance + # related tasks have plenty of time to clean up after a migration has been + # performed. + MIN_INTERVAL = 5.minutes.to_i + # Performs the background migration. # # See Gitlab::BackgroundMigration.perform for more information. + # + # class_name - The class name of the background migration to run. + # arguments - The arguments to pass to the migration class. def perform(class_name, arguments = []) - Gitlab::BackgroundMigration.perform(class_name, arguments) + should_perform, ttl = perform_and_ttl(class_name) + + if should_perform + Gitlab::BackgroundMigration.perform(class_name, arguments) + else + # If the lease could not be obtained this means either another process is + # running a migration of this class or we ran one recently. In this case + # we'll reschedule the job in such a way that it is picked up again around + # the time the lease expires. + self.class.perform_in(ttl || MIN_INTERVAL, class_name, arguments) + end + end + + def perform_and_ttl(class_name) + if always_perform? + # In test environments `perform_in` will run right away. This can then + # lead to stack level errors in the above `#perform`. To work around this + # we'll just perform the migration right away in the test environment. + [true, nil] + else + lease = lease_for(class_name) + + [lease.try_obtain, lease.ttl] + end + end + + def lease_for(class_name) + Gitlab::ExclusiveLease + .new("#{self.class.name}:#{class_name}", timeout: MIN_INTERVAL) + end + + def always_perform? + Rails.env.test? end end |