class Dynflow::ExecutionPlan::Steps::Abstract

Attributes

action_class[R]
action_id[R]
ended_at[R]
error[RW]
execution_plan_id[R]
execution_time[R]
id[R]
progress_weight[W]
queue[R]
real_time[R]
started_at[R]
state[R]
world[R]

Public Class Methods

new(execution_plan_id, id, state, action_class, action_id, error, world, started_at = nil, ended_at = nil, execution_time = 0.0, real_time = 0.0, progress_done = nil, progress_weight = nil, queue = nil) click to toggle source

rubocop:disable Metrics/ParameterLists

# File lib/dynflow/execution_plan/steps/abstract.rb, line 12
def initialize(execution_plan_id,
               id,
               state,
               action_class,
               action_id,
               error,
               world,
               started_at      = nil,
               ended_at        = nil,
               execution_time  = 0.0,
               real_time       = 0.0,
               progress_done   = nil,
               progress_weight = nil,
               queue           = nil)

  @id                = id || raise(ArgumentError, 'missing id')
  @execution_plan_id = Type! execution_plan_id, String
  @world             = Type! world, World
  @error             = Type! error, ExecutionPlan::Steps::Error, NilClass
  @started_at        = Type! started_at, Time, NilClass
  @ended_at          = Type! ended_at, Time, NilClass
  @execution_time    = Type! execution_time, Numeric
  @real_time         = Type! real_time, Numeric

  @progress_done     = Type! progress_done, Numeric, NilClass
  @progress_weight   = Type! progress_weight, Numeric, NilClass

  @queue             = Type! queue, Symbol, NilClass

  self.state = state.to_sym

  Child! action_class, Action
  @action_class = action_class

  @action_id = action_id || raise(ArgumentError, 'missing action_id')
end
states() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 70
def self.states
  @states ||= [:scheduling, :pending, :running, :success, :suspended, :skipping, :skipped, :error, :cancelled]
end

Protected Class Methods

new_from_hash(hash, execution_plan_id, world) click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 139
def self.new_from_hash(hash, execution_plan_id, world)
  check_class_matching hash
  new(execution_plan_id,
      hash[:id],
      hash[:state],
      Action.constantize(hash[:action_class]),
      hash[:action_id],
      hash_to_error(hash[:error]),
      world,
      string_to_time(hash[:started_at]),
      string_to_time(hash[:ended_at]),
      hash[:execution_time].to_f,
      hash[:real_time].to_f,
      hash[:progress_done].to_f,
      hash[:progress_weight].to_f,
      (hash[:queue] && hash[:queue].to_sym))
end

Public Instance Methods

action(execution_plan) click to toggle source

@return [Action] in presentation mode, intended for retrieving: progress information, details, human outputs, etc.

# File lib/dynflow/execution_plan/steps/abstract.rb, line 121
def action(execution_plan)
  world.persistence.load_action_for_presentation(execution_plan, action_id, self)
end
action_logger() click to toggle source

rubocop:enable Metrics/ParameterLists

# File lib/dynflow/execution_plan/steps/abstract.rb, line 50
def action_logger
  @world.action_logger
end
cancellable?() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 129
def cancellable?
  false
end
default_progress_done() click to toggle source

in specific states it's clear what progress the step is in

# File lib/dynflow/execution_plan/steps/abstract.rb, line 104
def default_progress_done
  case self.state
  when :success, :skipped
    1
  when :pending
    0
  end
end
execute(*args) click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 74
def execute(*args)
  raise NotImplementedError
end
mark_to_skip() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 58
def mark_to_skip
  raise NotImplementedError
end
persistence() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 62
def persistence
  world.persistence
end
phase() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 54
def phase
  raise NotImplementedError
end
progress_done() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 99
def progress_done
  default_progress_done || @progress_done || 0
end
progress_weight() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 113
def progress_weight
  @progress_weight || 0 # 0 means not calculated yet
end
save() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 66
def save
  persistence.save_step(self)
end
skippable?() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 125
def skippable?
  self.state == :error
end
to_hash() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 82
def to_hash
  recursive_to_hash execution_plan_uuid: execution_plan_id,
                    id:                  id,
                    state:               state,
                    class:               self.class.to_s,
                    action_class:        action_class.to_s,
                    action_id:           action_id,
                    error:               error,
                    started_at:          started_at,
                    ended_at:            ended_at,
                    execution_time:      execution_time,
                    real_time:           real_time,
                    progress_done:       progress_done,
                    progress_weight:     progress_weight,
                    queue:               queue
end
to_s() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 78
def to_s
  "#<#{self.class.name}:#{execution_plan_id}:#{id}>"
end
with_sub_plans?() click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 133
def with_sub_plans?
  false
end

Private Instance Methods

calculate_progress(action) click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 172
def calculate_progress(action)
  @progress_done, @progress_weight = action.calculated_progress
  if @progress_done.is_a?(Float) && !@progress_done.finite?
    action_logger.error("Unexpected progress value #{@progress_done} for step #{execution_plan_id}##{id}")
    @progress_done = 0
  end
end
update_step_telemetry(current_execution_time) click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 180
def update_step_telemetry(current_execution_time)
  Dynflow::Telemetry.with_instance do |t|
    if [:success, :skipped].include?(state)
      t.observe_histogram(:dynflow_step_real_time,
                          real_time * 1000,
                          :action => action_class.to_s, :phase => phase.to_s_humanized)
    end
    t.observe_histogram(:dynflow_step_execution_time,
                        current_execution_time * 1000,
                        :action => action_class.to_s, :phase => phase.to_s_humanized)
  end
end
with_meta_calculation(action, &block) click to toggle source
# File lib/dynflow/execution_plan/steps/abstract.rb, line 159
def with_meta_calculation(action, &block)
  start       = Time.now
  @started_at ||= start
  block.call
ensure
  calculate_progress(action)
  @ended_at = Time.now
  current_execution_time = @ended_at - start
  @execution_time += current_execution_time
  @real_time       = @ended_at - @started_at
  update_step_telemetry(current_execution_time)
end