<commit_before>class MigrateCreationStateToOwnershipWorker < ApplicationWorker
  sidekiq_options queue: "low_priority", retry: false
  # This timestamp is when the migration started - so any ownership created *after* this timestamp
  # is assumed to be correct
  END_TIMESTAMP = 1640109567
  TO_ENQUEUE = (ENV["MIGRATE_CREATION_QUEUE"] || 2500).to_i

  def self.creation_states
    CreationState.where("updated_at < ?", Time.at(END_TIMESTAMP)).order(updated_at: :desc)
  end

  def self.creation_states_with_earlier
    CreationState.where("updated_at > ?", Time.at(END_TIMESTAMP)).where(ownership_id: nil)
  end

  def self.migrate?(creation_state, ownership)
    creation_state.updated_at.to_i < END_TIMESTAMP &&
      ownership.created_at.to_i < END_TIMESTAMP
  end

  def self.enqueue
    # Skip if the queue is backing up
    return if ScheduledWorker.enqueued?
    creation_states.limit(TO_ENQUEUE)
      .pluck(:id).each { |id| MigrateCreationStateToOwnershipWorker.perform_async(id) }
  end

  def perform(creation_state_id, ownership_id = nil)
    creation_state = CreationState.find_by_id(creation_state_id)
    return if creation_state.blank?
    return if earlier_duplicate_creation_states?(creation_state)

    bike = Bike.unscoped.find_by_id(creation_state.bike_id)

    ownership = if ownership_id.present?
      Ownership.find(ownership_id)
    else
      bike.ownerships.first
    end

    if ownership.blank?
      # We want to update if possible - even if the bike is deleted, so don't check deleted before now
      raise "No Ownership - Bike: #{bike.id}" unless bike.deleted?
    else
      migrate(creation_state, ownership, bike)
    end
  end

  def earlier_duplicate_creation_states?(creation_state)
    # Handle duplicate creation states
    other_creation_states = CreationState.where(bike_id: creation_state.bike_id).where.not(id: creation_state.id)
    return false if other_creation_states.none?
    matching_creation_states = other_creation_states.select do |ocs|
      ocs.attributes.except("id", "created_at", "updated_at") == creation_state.attributes.except("id", "created_at", "updated_at")
    end
    matching_ids = matching_creation_states.map(&:id)
    if matching_creation_states.any?
      creation_state.update(registration_info: creation_state.registration_info.merge("deleted_creation_states" => matching_ids))
      matching_creation_states.map(&:destroy)
    end
    # Exit this method if there are no earlier creation states
    if other_creation_states.where.not(id: matching_ids).where("id < ?", creation_state.id).none?
      return false
    end
    creation_state.touch
    true
  end
<commit_msg>skip creation_state migration if ownership blank<commit_after>class MigrateCreationStateToOwnershipWorker < ApplicationWorker
  sidekiq_options queue: "low_priority", retry: false
  # This timestamp is when the migration started - so any ownership created *after* this timestamp
  # is assumed to be correct
  END_TIMESTAMP = 1640109567
  TO_ENQUEUE = (ENV["MIGRATE_CREATION_QUEUE"] || 2500).to_i

  def self.creation_states
    CreationState.where("updated_at < ?", Time.at(END_TIMESTAMP)).order(updated_at: :desc)
  end

  def self.creation_states_with_earlier
    CreationState.where("updated_at > ?", Time.at(END_TIMESTAMP)).where(ownership_id: nil)
  end

  def self.migrate?(creation_state, ownership)
    creation_state.updated_at.to_i < END_TIMESTAMP &&
      ownership.created_at.to_i < END_TIMESTAMP
  end

  def self.enqueue
    # Skip if the queue is backing up
    return if ScheduledWorker.enqueued?
    creation_states.limit(TO_ENQUEUE)
      .pluck(:id).each { |id| MigrateCreationStateToOwnershipWorker.perform_async(id) }
  end

  def perform(creation_state_id, ownership_id = nil)
    creation_state = CreationState.find_by_id(creation_state_id)
    return if creation_state.blank? || earlier_duplicate_creation_states?(creation_state)

    bike = Bike.unscoped.find_by_id(creation_state.bike_id)

    ownership = if ownership_id.present?
      Ownership.find(ownership_id)
    elsif bike.present?
      bike.ownerships.first
    end

    if ownership.blank?
      # Update creation_state so that it doesn't get looked up again
      return creation_state.update(updated_at: Time.current)
    else
      migrate(creation_state, ownership, bike)
    end
  end

  def earlier_duplicate_creation_states?(creation_state)
    # Handle duplicate creation states
    other_creation_states = CreationState.where(bike_id: creation_state.bike_id).where.not(id: creation_state.id)
    return false if other_creation_states.none?
    matching_creation_states = other_creation_states.select do |ocs|
      ocs.attributes.except("id", "created_at", "updated_at") == creation_state.attributes.except("id", "created_at", "updated_at")
    end
    matching_ids = matching_creation_states.map(&:id)
    if matching_creation_states.any?
      creation_state.update(registration_info: creation_state.registration_info.merge("deleted_creation_states" => matching_ids))
      matching_creation_states.map(&:destroy)
    end
    # Exit this method if there are no earlier creation states
    if other_creation_states.where.not(id: matching_ids).where("id < ?", creation_state.id).none?
      return false
    end
    creation_state.touch
    true
  end

{'fraction_non_alphanumeric': 0.0854878278920551, 'fraction_numerical': 0.005284015852047556, 'mean_word_length': 4.447070914696814, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 7, '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': '2493097', 'n_tokens_mistral': 1723, 'n_tokens_neox': 1637, 'n_words': 346}