<commit_before>require 'io/wait'

class MiqWorker < ApplicationRecord
  include_concern 'ContainerCommon'
  include_concern 'SystemdCommon'
  include UuidMixin

  before_destroy :error_out_tasks_with_active_queue_message, :log_destroy_of_worker_messages

  belongs_to :miq_server
  has_many   :messages,           :as => :handler, :class_name => 'MiqQueue'
  has_many   :active_messages,    -> { where(["state = ?", "dequeue"]) }, :as => :handler, :class_name => 'MiqQueue'
  has_many   :ready_messages,     -> { where(["state = ?", "ready"]) }, :as => :handler, :class_name => 'MiqQueue'
  has_many   :processed_messages, -> { where(["state != ?", "ready"]) }, :as => :handler, :class_name => 'MiqQueue', :dependent => :destroy

  virtual_column :friendly_name, :type => :string
  virtual_column :uri_or_queue_name, :type => :string

  scope :with_miq_server_id, ->(server_id) { where(:miq_server_id => server_id) }
  scope :with_status,        ->(status)    { where(:status => status) }

  class_attribute :my_guid

  STATUS_CREATING = 'creating'.freeze
  STATUS_STARTING = 'starting'.freeze
  STATUS_STARTED  = 'started'.freeze
  STATUS_READY    = 'ready'.freeze
  STATUS_WORKING  = 'working'.freeze
  STATUS_STOPPING = 'stopping'.freeze
  STATUS_STOPPED  = 'stopped'.freeze
  STATUS_KILLED   = 'killed'.freeze
  STATUS_ABORTED  = 'aborted'.freeze

  STATUSES_STARTING = [STATUS_CREATING, STATUS_STARTING]
  STATUSES_CURRENT  = [STATUS_STARTED, STATUS_READY, STATUS_WORKING]
  STATUSES_STOPPED  = [STATUS_STOPPED, STATUS_KILLED, STATUS_ABORTED]
  STATUSES_CURRENT_OR_STARTING = STATUSES_CURRENT + STATUSES_STARTING
  STATUSES_ALIVE    = STATUSES_CURRENT_OR_STARTING + [STATUS_STOPPING]
  PROCESS_INFO_FIELDS = %i(priority memory_usage percent_memory percent_cpu memory_size cpu_time proportional_set_size unique_set_size)

  PROCESS_TITLE_PREFIX = "MIQ:".freeze

  def self.atShutdown
    stop_workers
  end

  class << self
    attr_writer :workers
  end

  def self.bundler_groups
    %w[manageiq_default ui_dependencies]
  end

  def self.kill_priority
    raise NotImplementedError, ".kill_priority must be implemented in a subclass"
  end

  def self.workers
    return 0 unless has_required_role?
    return @workers.call if @workers.kind_of?(Proc)
    return @workers unless @workers.nil?
    workers_configured_count
  end

  def self.scalable?
    maximum_workers_count.nil? || maximum_workers_count > 1
  end

  def scalable?
    self.class.scalable?
  end

  def self.workers_configured_count
    count = worker_settings[:count]
    if maximum_workers_count.kind_of?(Integer)
      count = maximum_workers_count if maximum_workers_count < count
    end
    count
  end

  def self.concrete_subclasses
    leaf_subclasses | descendants.select { |d| d.try(:acts_as_sti_leaf_class?) }
  end

  class_attribute :default_queue_name, :required_roles, :maximum_workers_count, :include_stopping_workers_on_synchronize, :rails_worker
  self.include_stopping_workers_on_synchronize = false
  self.required_roles = []
  self.rails_worker = true

  def self.server_scope
    return current_scope if current_scope && current_scope.where_values_hash.include?('miq_server_id')
    where(:miq_server_id => MiqServer.my_server&.id)
  end

  CONDITION_CURRENT = {:status => STATUSES_CURRENT}
  def self.find_current
    server_scope.where(CONDITION_CURRENT)
  end<commit_msg>Allow a Proc for self.rails_worker<commit_after>require 'io/wait'

class MiqWorker < ApplicationRecord
  include_concern 'ContainerCommon'
  include_concern 'SystemdCommon'
  include UuidMixin

  before_destroy :error_out_tasks_with_active_queue_message, :log_destroy_of_worker_messages

  belongs_to :miq_server
  has_many   :messages,           :as => :handler, :class_name => 'MiqQueue'
  has_many   :active_messages,    -> { where(["state = ?", "dequeue"]) }, :as => :handler, :class_name => 'MiqQueue'
  has_many   :ready_messages,     -> { where(["state = ?", "ready"]) }, :as => :handler, :class_name => 'MiqQueue'
  has_many   :processed_messages, -> { where(["state != ?", "ready"]) }, :as => :handler, :class_name => 'MiqQueue', :dependent => :destroy

  virtual_column :friendly_name, :type => :string
  virtual_column :uri_or_queue_name, :type => :string

  scope :with_miq_server_id, ->(server_id) { where(:miq_server_id => server_id) }
  scope :with_status,        ->(status)    { where(:status => status) }

  class_attribute :my_guid

  STATUS_CREATING = 'creating'.freeze
  STATUS_STARTING = 'starting'.freeze
  STATUS_STARTED  = 'started'.freeze
  STATUS_READY    = 'ready'.freeze
  STATUS_WORKING  = 'working'.freeze
  STATUS_STOPPING = 'stopping'.freeze
  STATUS_STOPPED  = 'stopped'.freeze
  STATUS_KILLED   = 'killed'.freeze
  STATUS_ABORTED  = 'aborted'.freeze

  STATUSES_STARTING = [STATUS_CREATING, STATUS_STARTING]
  STATUSES_CURRENT  = [STATUS_STARTED, STATUS_READY, STATUS_WORKING]
  STATUSES_STOPPED  = [STATUS_STOPPED, STATUS_KILLED, STATUS_ABORTED]
  STATUSES_CURRENT_OR_STARTING = STATUSES_CURRENT + STATUSES_STARTING
  STATUSES_ALIVE    = STATUSES_CURRENT_OR_STARTING + [STATUS_STOPPING]
  PROCESS_INFO_FIELDS = %i(priority memory_usage percent_memory percent_cpu memory_size cpu_time proportional_set_size unique_set_size)

  PROCESS_TITLE_PREFIX = "MIQ:".freeze

  def self.atShutdown
    stop_workers
  end

  class << self
    attr_writer :workers, :rails_worker
  end

  def self.bundler_groups
    %w[manageiq_default ui_dependencies]
  end

  def self.kill_priority
    raise NotImplementedError, ".kill_priority must be implemented in a subclass"
  end

  def self.workers
    return 0 unless has_required_role?
    return @workers.call if @workers.kind_of?(Proc)
    return @workers unless @workers.nil?
    workers_configured_count
  end

  def self.rails_worker?
    @rails_worker.kind_of?(Proc) ? @rails_worker.call : @rails_worker
  end

  def self.scalable?
    maximum_workers_count.nil? || maximum_workers_count > 1
  end

  def scalable?
    self.class.scalable?
  end

  def self.workers_configured_count
    count = worker_settings[:count]
    if maximum_workers_count.kind_of?(Integer)
      count = maximum_workers_count if maximum_workers_count < count
    end
    count
  end

  def self.concrete_subclasses
    leaf_subclasses | descendants.select { |d| d.try(:acts_as_sti_leaf_class?) }
  end

  class_attribute :default_queue_name, :required_roles, :maximum_workers_count, :include_stopping_workers_on_synchronize
  self.include_stopping_workers_on_synchronize = false
  self.required_roles = []
  self.rails_worker = true

  def self.server_scope
    return current_scope if current_scope && current_scope.where_values_hash.include?('miq_server_id')
    where(:miq_server_id => MiqServer.my_server&.id)
  end

  CONDITION_CURRENT = {:status => STATUSES_CURRENT}
  def self.find_current
    server_scope.where(CONDITION_CURRENT)
  end
{'fraction_non_alphanumeric': 0.0968681718863802, 'fraction_numerical': 0.000582665695557174, 'mean_word_length': 4.721666666666667, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 45, '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': '3360504', 'n_tokens_mistral': 2415, 'n_tokens_neox': 2300, 'n_words': 439}