<commit_before>require 'set'
require 'infrastructure_facades/infrastructure_task_logger'
require_relative 'infrastructure_errors'

class SimulationManager
  extend Forwardable

  attr_reader :record
  attr_reader :infrastructure
  attr_reader :logger

  def_delegators :@record,
                 :state, :init_time_exceeded?, :experiment_end?,
                 :time_limit_exceeded?, :should_destroy?, :stopping_time_exceeded?

  def initialize(record, infrastructure)
    unless record.state == :error
      begin
        record.validate
      rescue InfrastructureErrors::InvalidCredentialsError, InfrastructureErrors::NoCredentialsError
        Rails.logger.warn "Record #{record.id} for infrastructure #{infrastructure.short_name} has invalid credentials"
        record.store_error('credentials')
      rescue Exception => error
        Rails.logger.warn "Record #{record.id} for infrastructure #{infrastructure.short_name} did not pass "/
                              "validation due to error: #{error.to_s}\n#{error.backtrace.join("\n")}"
        record.store_error('validation', error.to_s)
      end
    end

    @record = record
    @infrastructure = infrastructure
    @logger = InfrastructureTaskLogger.new(infrastructure.short_name, record.resource_id)
  end

  def self.all_resource_states
    @@all_resource_states = [
        :not_available,
        :available,
        :initializing,
        :ready,
        :running_sm,
        :released
    ]
  end

  def all_resource_states
    SimulationManager.all_resource_states
  end

  # Delegates set_state to record and if it is ERROR, tries to stop resource if it was acqured
  def set_state(state)
    stop if state == :error and [:initializing, :ready, :running_sm].include? resource_status
    record.set_state(state)
  end

  def monitoring_cases
    @monitoring_cases ||= generate_monitoring_cases
  end

  def monitoring_order
    @monitoring_order ||= monitoring_cases.keys
  end

  def generate_monitoring_cases
    {
        error_resource_status: {
            source_states: SimulationManagerRecord::POSSIBLE_STATES - [:error],
            target_state: :error,
            resource_status: [:error],
            effect: :store_error_resource_status,
            message: 'Resource has ERROR status - marking record as invalid'
        },
        experiment_end: {
            source_states: [:created, :initializing, :running],
            target_state: :terminating,
            effect: :stop,
            condition: :experiment_end?,
            message: 'Experiment finished - destroying Simulation Manager'
        },
        prepare_resource: {
            source_states: [:created],
            target_state: :initializing,
            resource_status: [:available],
            effect: :prepare_resource,
            message: 'Preparing resource for Simulation Manager installation'
        },
        init_time_exceeded: {
            source_states: [:initializing],
            target_state: :initializing,
            condition: :init_time_exceeded?,
            effect: :restart,
            message: 'Initialization time exceeded - trying to restart resource'
        },
        install: {
            source_states: [:initializing],
            target_state: :running,
            resource_status: [:ready],
            effect: :install,
            message: 'Simulation Manager will be installed on resource now'
        },
        detect_sm_started: {
            source_states: [:initializing],
            target_state: :running,
            resource_status: [:running_sm, :released],
            message: 'Detected that Simulation Manager is running'
        },
        running_time_limit_exceeded: {
            source_states: [:running],
            target_state: :terminating,
            condition: :time_limit_exceeded?,
            effect: :stop,
            message: 'Time limit exceeded - terminating'
        },
        terminated_untimely: {
            source_states: [:running, :initializing],
            target_state: :error,
            resource_status: all_resource_states - [:running_sm],
            condition: :should_not_be_destroyed?,
            effect: :store_terminated_error,
            message: 'Simulation Manager has been terminated untimely - setting to ERROR state'
        },
        not_started_time_limit: {
            source_states: [:created],
            target_state: :error,
            resource_status: [:not_available, :available, :initializing],
            condition: :time_limit_exceeded?,
            effect: :store_not_started_error,<commit_msg>Reverting buggy state transition (initializing with terminated_untimely)<commit_after>require 'set'
require 'infrastructure_facades/infrastructure_task_logger'
require_relative 'infrastructure_errors'

class SimulationManager
  extend Forwardable

  attr_reader :record
  attr_reader :infrastructure
  attr_reader :logger

  def_delegators :@record,
                 :state, :init_time_exceeded?, :experiment_end?,
                 :time_limit_exceeded?, :should_destroy?, :stopping_time_exceeded?

  def initialize(record, infrastructure)
    unless record.state == :error
      begin
        record.validate
      rescue InfrastructureErrors::InvalidCredentialsError, InfrastructureErrors::NoCredentialsError
        Rails.logger.warn "Record #{record.id} for infrastructure #{infrastructure.short_name} has invalid credentials"
        record.store_error('credentials')
      rescue Exception => error
        Rails.logger.warn "Record #{record.id} for infrastructure #{infrastructure.short_name} did not pass "/
                              "validation due to error: #{error.to_s}\n#{error.backtrace.join("\n")}"
        record.store_error('validation', error.to_s)
      end
    end

    @record = record
    @infrastructure = infrastructure
    @logger = InfrastructureTaskLogger.new(infrastructure.short_name, record.resource_id)
  end

  def self.all_resource_states
    @@all_resource_states = [
        :not_available,
        :available,
        :initializing,
        :ready,
        :running_sm,
        :released
    ]
  end

  def all_resource_states
    SimulationManager.all_resource_states
  end

  # Delegates set_state to record and if it is ERROR, tries to stop resource if it was acqured
  def set_state(state)
    stop if state == :error and [:initializing, :ready, :running_sm].include? resource_status
    record.set_state(state)
  end

  def monitoring_cases
    @monitoring_cases ||= generate_monitoring_cases
  end

  def monitoring_order
    @monitoring_order ||= monitoring_cases.keys
  end

  def generate_monitoring_cases
    {
        error_resource_status: {
            source_states: SimulationManagerRecord::POSSIBLE_STATES - [:error],
            target_state: :error,
            resource_status: [:error],
            effect: :store_error_resource_status,
            message: 'Resource has ERROR status - marking record as invalid'
        },
        experiment_end: {
            source_states: [:created, :initializing, :running],
            target_state: :terminating,
            effect: :stop,
            condition: :experiment_end?,
            message: 'Experiment finished - destroying Simulation Manager'
        },
        prepare_resource: {
            source_states: [:created],
            target_state: :initializing,
            resource_status: [:available],
            effect: :prepare_resource,
            message: 'Preparing resource for Simulation Manager installation'
        },
        init_time_exceeded: {
            source_states: [:initializing],
            target_state: :initializing,
            condition: :init_time_exceeded?,
            effect: :restart,
            message: 'Initialization time exceeded - trying to restart resource'
        },
        install: {
            source_states: [:initializing],
            target_state: :running,
            resource_status: [:ready],
            effect: :install,
            message: 'Simulation Manager will be installed on resource now'
        },
        detect_sm_started: {
            source_states: [:initializing],
            target_state: :running,
            resource_status: [:running_sm, :released],
            message: 'Detected that Simulation Manager is running'
        },
        running_time_limit_exceeded: {
            source_states: [:running],
            target_state: :terminating,
            condition: :time_limit_exceeded?,
            effect: :stop,
            message: 'Time limit exceeded - terminating'
        },
        terminated_untimely: {
            source_states: [:running],
            target_state: :error,
            resource_status: all_resource_states - [:running_sm],
            condition: :should_not_be_destroyed?,
            effect: :store_terminated_error,
            message: 'Simulation Manager has been terminated untimely - setting to ERROR state'
        },
        not_started_time_limit: {
            source_states: [:created, :initializing],
            target_state: :error,
            resource_status: [:not_available, :available, :initializing],
            condition: :time_limit_exceeded?,
            effect: :store_not_started_error,
{'fraction_non_alphanumeric': 0.08384790380240494, 'fraction_numerical': 0.0, 'mean_word_length': 2.5196340068623715, 'pattern_counts': {'":': 0, '<': 3, '<?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': '932471', 'n_tokens_mistral': 2466, 'n_tokens_neox': 2401, 'n_words': 571}