59 lines
1.6 KiB
Ruby
59 lines
1.6 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
module Gitlab
|
||
|
module BackgroundMigration
|
||
|
# The class to populates the star counter of projects
|
||
|
class PopulateProjectsStarCount < BatchedMigrationJob
|
||
|
MAX_UPDATE_RETRIES = 3
|
||
|
|
||
|
operation_name :update_all
|
||
|
|
||
|
def perform
|
||
|
each_sub_batch do |sub_batch|
|
||
|
update_with_retry(sub_batch)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
# rubocop:disable Database/RescueQueryCanceled
|
||
|
# rubocop:disable Database/RescueStatementTimeout
|
||
|
def update_with_retry(sub_batch)
|
||
|
update_attempt = 1
|
||
|
|
||
|
begin
|
||
|
update_batch(sub_batch)
|
||
|
rescue ActiveRecord::StatementTimeout, ActiveRecord::QueryCanceled => e
|
||
|
update_attempt += 1
|
||
|
|
||
|
if update_attempt <= MAX_UPDATE_RETRIES
|
||
|
sleep(5)
|
||
|
retry
|
||
|
end
|
||
|
|
||
|
raise e
|
||
|
end
|
||
|
end
|
||
|
# rubocop:enable Database/RescueQueryCanceled
|
||
|
# rubocop:enable Database/RescueStatementTimeout
|
||
|
|
||
|
def update_batch(sub_batch)
|
||
|
ApplicationRecord.connection.execute <<~SQL
|
||
|
WITH batched_relation AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (#{sub_batch.select(:id).to_sql})
|
||
|
UPDATE projects
|
||
|
SET star_count = (
|
||
|
SELECT COUNT(*)
|
||
|
FROM users_star_projects
|
||
|
INNER JOIN users
|
||
|
ON users_star_projects.user_id = users.id
|
||
|
WHERE users_star_projects.project_id = batched_relation.id
|
||
|
AND users.state = 'active'
|
||
|
)
|
||
|
FROM batched_relation
|
||
|
WHERE projects.id = batched_relation.id
|
||
|
SQL
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|