<commit_before>module Projects
  class PropagateService
    BATCH_SIZE = 100

    def self.propagate(*args)
      new(*args).propagate
    end

    def initialize(template)
      @template = template
    end

    def propagate
      return unless @template&.active

      Rails.logger.info("Propagating services for template #{@template.id}")

      propagate_projects_with_template
    end

    private

    def propagate_projects_with_template
      loop do
        batch = project_ids_batch

        bulk_create_from_template(batch)

        break if batch.size < BATCH_SIZE
      end
    end

    def bulk_create_from_template(batch)
      service_hash_list = batch.map do |project_id|
        service_hash.merge('project_id' => project_id)
      end

      Project.transaction do
        Service.create!(service_hash_list)
      end
    end

    def project_ids_batch
      Project.connection.execute(
        <<-SQL
          SELECT id
          FROM projects
          WHERE NOT EXISTS (
            SELECT true
            FROM services
            WHERE services.project_id = projects.id
            AND services.type = '#{@template.type}'
          )
          LIMIT #{BATCH_SIZE}
      SQL
      ).to_a.flatten
    end

    def service_hash
      @service_hash ||= @template.as_json(methods: :type).except('id', 'template')
    end
  end
end<commit_msg>use select_values<commit_after>module Projects
  class PropagateService
    BATCH_SIZE = 100

    def self.propagate(*args)
      new(*args).propagate
    end

    def initialize(template)
      @template = template
    end

    def propagate
      return unless @template&.active

      Rails.logger.info("Propagating services for template #{@template.id}")

      propagate_projects_with_template
    end

    private

    def propagate_projects_with_template
      loop do
        batch = project_ids_batch

        bulk_create_from_template(batch)

        break if batch.size < BATCH_SIZE
      end
    end

    def bulk_create_from_template(batch)
      service_hash_list = batch.map do |project_id|
        service_hash.merge('project_id' => project_id)
      end

      Project.transaction do
        Service.create!(service_hash_list)
      end
    end

    def project_ids_batch
      Project.connection.select_values(
        <<-SQL
          SELECT id
          FROM projects
          WHERE NOT EXISTS (
            SELECT true
            FROM services
            WHERE services.project_id = projects.id
            AND services.type = '#{@template.type}'
          )
          LIMIT #{BATCH_SIZE}
      SQL
      )
    end

    def service_hash
      @service_hash ||= @template.as_json(methods: :type).except('id', 'template')
    end
  end
end
{'fraction_non_alphanumeric': 0.07045871559633028, 'fraction_numerical': 0.0022018348623853213, 'mean_word_length': 2.1047835990888384, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6708083', 'n_tokens_mistral': 802, 'n_tokens_neox': 759, 'n_words': 179}