summaryrefslogtreecommitdiff
path: root/lib/gitlab/database/background_migration/batched_job.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/database/background_migration/batched_job.rb')
-rw-r--r--lib/gitlab/database/background_migration/batched_job.rb45
1 files changed, 45 insertions, 0 deletions
diff --git a/lib/gitlab/database/background_migration/batched_job.rb b/lib/gitlab/database/background_migration/batched_job.rb
index 9a1dc4ee17d..03bd02d7554 100644
--- a/lib/gitlab/database/background_migration/batched_job.rb
+++ b/lib/gitlab/database/background_migration/batched_job.rb
@@ -44,6 +44,51 @@ module Gitlab
# TODO: Switch to individual job interval (prereq: https://gitlab.com/gitlab-org/gitlab/-/issues/328801)
duration.to_f / batched_migration.interval
end
+
+ def split_and_retry!
+ with_lock do
+ raise 'Only failed jobs can be split' unless failed?
+
+ new_batch_size = batch_size / 2
+
+ raise 'Job cannot be split further' if new_batch_size < 1
+
+ batching_strategy = batched_migration.batch_class.new
+ next_batch_bounds = batching_strategy.next_batch(
+ batched_migration.table_name,
+ batched_migration.column_name,
+ batch_min_value: min_value,
+ batch_size: new_batch_size
+ )
+ midpoint = next_batch_bounds.last
+
+ # We don't want the midpoint to go over the existing max_value because
+ # those IDs would already be in the next batched migration job.
+ # This could happen when a lot of records in the current batch are deleted.
+ #
+ # In this case, we just lower the batch size so that future calls to this
+ # method could eventually split the job if it continues to fail.
+ if midpoint >= max_value
+ update!(batch_size: new_batch_size, attempts: 0)
+ else
+ old_max_value = max_value
+
+ update!(
+ batch_size: new_batch_size,
+ max_value: midpoint,
+ attempts: 0,
+ started_at: nil,
+ finished_at: nil,
+ metrics: {}
+ )
+
+ new_record = dup
+ new_record.min_value = midpoint.next
+ new_record.max_value = old_max_value
+ new_record.save!
+ end
+ end
+ end
end
end
end