diff options
Diffstat (limited to 'lib/gitlab/background_migration/populate_projects_star_count.rb')
-rw-r--r-- | lib/gitlab/background_migration/populate_projects_star_count.rb | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/lib/gitlab/background_migration/populate_projects_star_count.rb b/lib/gitlab/background_migration/populate_projects_star_count.rb new file mode 100644 index 00000000000..085d576637e --- /dev/null +++ b/lib/gitlab/background_migration/populate_projects_star_count.rb @@ -0,0 +1,58 @@ +# 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 |