# frozen_string_literal: true module Gitlab module BackgroundMigration # rubocop:disable Style/Documentation class PopulateVulnerabilityReads include Gitlab::Database::DynamicModelHelpers PAUSE_SECONDS = 0.1 def perform(start_id, end_id, sub_batch_size) vulnerability_model.where(id: start_id..end_id).each_batch(of: sub_batch_size) do |sub_batch| first, last = sub_batch.pluck(Arel.sql('min(id), max(id)')).first connection.execute(insert_query(first, last)) sleep PAUSE_SECONDS end mark_job_as_succeeded(start_id, end_id, sub_batch_size) end private def vulnerability_model define_batchable_model('vulnerabilities', connection: connection) end def connection ActiveRecord::Base.connection end def insert_query(start_id, end_id) <<~SQL INSERT INTO vulnerability_reads ( vulnerability_id, project_id, scanner_id, report_type, severity, state, has_issues, resolved_on_default_branch, uuid, location_image ) SELECT vulnerabilities.id, vulnerabilities.project_id, vulnerability_scanners.id, vulnerabilities.report_type, vulnerabilities.severity, vulnerabilities.state, CASE WHEN vulnerability_issue_links.vulnerability_id IS NOT NULL THEN true ELSE false END has_issues, vulnerabilities.resolved_on_default_branch, vulnerability_occurrences.uuid::uuid, vulnerability_occurrences.location ->> 'image' FROM vulnerabilities INNER JOIN vulnerability_occurrences ON vulnerability_occurrences.vulnerability_id = vulnerabilities.id INNER JOIN vulnerability_scanners ON vulnerability_scanners.id = vulnerability_occurrences.scanner_id LEFT JOIN vulnerability_issue_links ON vulnerability_issue_links.vulnerability_id = vulnerabilities.id WHERE vulnerabilities.id BETWEEN #{start_id} AND #{end_id} ON CONFLICT(vulnerability_id) DO NOTHING; SQL end def mark_job_as_succeeded(*arguments) Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded( self.class.name.demodulize, arguments ) end end # rubocop:enable Style/Documentation end end